]> git.lyx.org Git - lyx.git/blob - 3rdparty/boost/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp
Update to boost 1.72
[lyx.git] / 3rdparty / boost / boost / smart_ptr / detail / sp_counted_base_std_atomic.hpp
1 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
2 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
3
4 // MS compatible compilers support #pragma once
5
6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
7 # pragma once
8 #endif
9
10 //  detail/sp_counted_base_std_atomic.hpp - C++11 std::atomic
11 //
12 //  Copyright (c) 2007, 2013 Peter Dimov
13 //
14 //  Distributed under the Boost Software License, Version 1.0.
15 //  See accompanying file LICENSE_1_0.txt or copy at
16 //  http://www.boost.org/LICENSE_1_0.txt
17
18 #include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
19 #include <boost/smart_ptr/detail/sp_noexcept.hpp>
20 #include <boost/config.hpp>
21 #include <atomic>
22 #include <cstdint>
23
24 namespace boost
25 {
26
27 namespace detail
28 {
29
30 inline void atomic_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
31 {
32     pw->fetch_add( 1, std::memory_order_relaxed );
33 }
34
35 inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
36 {
37     return pw->fetch_sub( 1, std::memory_order_acq_rel );
38 }
39
40 inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
41 {
42     // long r = *pw;
43     // if( r != 0 ) ++*pw;
44     // return r;
45
46     std::int_least32_t r = pw->load( std::memory_order_relaxed );
47
48     for( ;; )
49     {
50         if( r == 0 )
51         {
52             return r;
53         }
54
55         if( pw->compare_exchange_weak( r, r + 1, std::memory_order_relaxed, std::memory_order_relaxed ) )
56         {
57             return r;
58         }
59     }    
60 }
61
62 class BOOST_SYMBOL_VISIBLE sp_counted_base
63 {
64 private:
65
66     sp_counted_base( sp_counted_base const & );
67     sp_counted_base & operator= ( sp_counted_base const & );
68
69     std::atomic_int_least32_t use_count_;   // #shared
70     std::atomic_int_least32_t weak_count_;  // #weak + (#shared != 0)
71
72 public:
73
74     sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
75     {
76     }
77
78     virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
79     {
80     }
81
82     // dispose() is called when use_count_ drops to zero, to release
83     // the resources managed by *this.
84
85     virtual void dispose() BOOST_SP_NOEXCEPT = 0;
86
87     // destroy() is called when weak_count_ drops to zero.
88
89     virtual void destroy() BOOST_SP_NOEXCEPT
90     {
91         delete this;
92     }
93
94     virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
95     virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
96     virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
97
98     void add_ref_copy() BOOST_SP_NOEXCEPT
99     {
100         atomic_increment( &use_count_ );
101     }
102
103     bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
104     {
105         return atomic_conditional_increment( &use_count_ ) != 0;
106     }
107
108     void release() BOOST_SP_NOEXCEPT
109     {
110         if( atomic_decrement( &use_count_ ) == 1 )
111         {
112             dispose();
113             weak_release();
114         }
115     }
116
117     void weak_add_ref() BOOST_SP_NOEXCEPT
118     {
119         atomic_increment( &weak_count_ );
120     }
121
122     void weak_release() BOOST_SP_NOEXCEPT
123     {
124         if( atomic_decrement( &weak_count_ ) == 1 )
125         {
126             destroy();
127         }
128     }
129
130     long use_count() const BOOST_SP_NOEXCEPT
131     {
132         return use_count_.load( std::memory_order_acquire );
133     }
134 };
135
136 } // namespace detail
137
138 } // namespace boost
139
140 #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED