6ec1d56e594ff0c489c3526354656dcb6874358b
[platform/upstream/boost.git] / boost / interprocess / smart_ptr / detail / sp_counted_base_atomic.hpp
1 #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED
2 #define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED
3
4 // MS compatible compilers support #pragma once
5
6 #if defined(_MSC_VER)
7 # pragma once
8 #endif
9
10 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
11 //  Copyright 2004-2005 Peter Dimov
12 //  Copyright 2007-2012 Ion Gaztanaga
13 //
14 // Distributed under the Boost Software License, Version 1.0. (See
15 // accompanying file LICENSE_1_0.txt or copy at
16 // http://www.boost.org/LICENSE_1_0.txt)
17 //
18 //
19 //  Lock-free algorithm by Alexander Terekhov
20 //
21 //  Thanks to Ben Hitchings for the #weak + (#shared != 0)
22 //  formulation
23 //
24
25 #include <boost/interprocess/detail/config_begin.hpp>
26 #include <boost/interprocess/detail/workaround.hpp>
27
28 #include <boost/interprocess/detail/atomic.hpp>
29 #include <typeinfo>
30
31 namespace boost {
32
33 namespace interprocess {
34
35 namespace ipcdetail {
36
37 class sp_counted_base
38 {
39 private:
40
41     sp_counted_base( sp_counted_base const & );
42     sp_counted_base & operator= ( sp_counted_base const & );
43
44     boost::uint32_t use_count_;        // #shared
45     boost::uint32_t weak_count_;       // #weak + (#shared != 0)
46
47 public:
48
49     sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
50     {}
51
52     ~sp_counted_base() // nothrow
53     {}
54
55     void add_ref_copy()
56     {
57         ipcdetail::atomic_inc32( &use_count_ );
58     }
59
60     bool add_ref_lock() // true on success
61     {
62         for( ;; )
63         {
64             boost::uint32_t tmp = static_cast< boost::uint32_t const volatile& >( use_count_ );
65             if( tmp == 0 ) return false;
66             if( ipcdetail::atomic_cas32( &use_count_, tmp + 1, tmp ) == tmp )
67                return true;
68         }
69     }
70
71    bool ref_release() // nothrow
72    { return 1 == ipcdetail::atomic_dec32( &use_count_ );  }
73
74    void weak_add_ref() // nothrow
75    { ipcdetail::atomic_inc32( &weak_count_ ); }
76
77    bool weak_release() // nothrow
78    { return 1 == ipcdetail::atomic_dec32( &weak_count_ ); }
79
80    long use_count() const // nothrow
81    { return (long)static_cast<boost::uint32_t const volatile &>( use_count_ ); }
82 };
83
84 } // namespace ipcdetail
85
86 } // namespace interprocess
87
88 } // namespace boost
89
90 #include <boost/interprocess/detail/config_end.hpp>
91
92 #endif  // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED