]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/smart_ptr/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / smart_ptr / include / boost / smart_ptr / detail / sp_counted_base_clang.hpp
1 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
2 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_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_clang.hpp - __c11 clang intrinsics
11 //
12 // Copyright (c) 2007, 2013, 2015 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/detail/sp_typeinfo.hpp>
19 #include <boost/cstdint.hpp>
20
21 namespace boost
22 {
23
24 namespace detail
25 {
26
27 typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t;
28
29 inline void atomic_increment( atomic_int_least32_t * pw )
30 {
31 __c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
32 }
33
34 inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw )
35 {
36 return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL );
37 }
38
39 inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw )
40 {
41 // long r = *pw;
42 // if( r != 0 ) ++*pw;
43 // return r;
44
45 boost::int_least32_t r = __c11_atomic_load( pw, __ATOMIC_RELAXED );
46
47 for( ;; )
48 {
49 if( r == 0 )
50 {
51 return r;
52 }
53
54 if( __c11_atomic_compare_exchange_weak( pw, &r, r + 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) )
55 {
56 return r;
57 }
58 }
59 }
60
61 #if defined(__clang__)
62 # pragma clang diagnostic push
63 # pragma clang diagnostic ignored "-Wweak-vtables"
64 #endif
65
66 class sp_counted_base
67 {
68 private:
69
70 sp_counted_base( sp_counted_base const & );
71 sp_counted_base & operator= ( sp_counted_base const & );
72
73 atomic_int_least32_t use_count_; // #shared
74 atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
75
76 public:
77
78 sp_counted_base()
79 {
80 __c11_atomic_init( &use_count_, 1 );
81 __c11_atomic_init( &weak_count_, 1 );
82 }
83
84 virtual ~sp_counted_base() // nothrow
85 {
86 }
87
88 // dispose() is called when use_count_ drops to zero, to release
89 // the resources managed by *this.
90
91 virtual void dispose() = 0; // nothrow
92
93 // destroy() is called when weak_count_ drops to zero.
94
95 virtual void destroy() // nothrow
96 {
97 delete this;
98 }
99
100 virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
101 virtual void * get_untyped_deleter() = 0;
102
103 void add_ref_copy()
104 {
105 atomic_increment( &use_count_ );
106 }
107
108 bool add_ref_lock() // true on success
109 {
110 return atomic_conditional_increment( &use_count_ ) != 0;
111 }
112
113 void release() // nothrow
114 {
115 if( atomic_decrement( &use_count_ ) == 1 )
116 {
117 dispose();
118 weak_release();
119 }
120 }
121
122 void weak_add_ref() // nothrow
123 {
124 atomic_increment( &weak_count_ );
125 }
126
127 void weak_release() // nothrow
128 {
129 if( atomic_decrement( &weak_count_ ) == 1 )
130 {
131 destroy();
132 }
133 }
134
135 long use_count() const // nothrow
136 {
137 return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE );
138 }
139 };
140
141 #if defined(__clang__)
142 # pragma clang diagnostic pop
143 #endif
144
145 } // namespace detail
146
147 } // namespace boost
148
149 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED