]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/smart_ptr/detail/sp_counted_base_clang.hpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / 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_local_deleter( sp_typeinfo const & ti ) = 0;
102 virtual void * get_untyped_deleter() = 0;
103
104 void add_ref_copy()
105 {
106 atomic_increment( &use_count_ );
107 }
108
109 bool add_ref_lock() // true on success
110 {
111 return atomic_conditional_increment( &use_count_ ) != 0;
112 }
113
114 void release() // nothrow
115 {
116 if( atomic_decrement( &use_count_ ) == 1 )
117 {
118 dispose();
119 weak_release();
120 }
121 }
122
123 void weak_add_ref() // nothrow
124 {
125 atomic_increment( &weak_count_ );
126 }
127
128 void weak_release() // nothrow
129 {
130 if( atomic_decrement( &weak_count_ ) == 1 )
131 {
132 destroy();
133 }
134 }
135
136 long use_count() const // nothrow
137 {
138 return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE );
139 }
140 };
141
142 #if defined(__clang__)
143 # pragma clang diagnostic pop
144 #endif
145
146 } // namespace detail
147
148 } // namespace boost
149
150 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED