]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/interprocess/smart_ptr/detail/shared_count.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / interprocess / smart_ptr / detail / shared_count.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // This file is the adaptation for Interprocess of boost/detail/shared_count.hpp
4 //
5 // (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003
6 // (C) Copyright Peter Dimov 2004-2005
7 // (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
8 // Software License, Version 1.0. (See accompanying file
9 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // See http://www.boost.org/libs/interprocess for documentation.
12 //
13 //////////////////////////////////////////////////////////////////////////////
14 #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
15 #define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
16
17 #ifndef BOOST_CONFIG_HPP
18 # include <boost/config.hpp>
19 #endif
20 #
21 #if defined(BOOST_HAS_PRAGMA_ONCE)
22 # pragma once
23 #endif
24
25 #include <boost/interprocess/detail/config_begin.hpp>
26 #include <boost/interprocess/detail/workaround.hpp>
27
28 #include <boost/intrusive/pointer_traits.hpp>
29 #include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
30 #include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
31 #include <boost/interprocess/detail/utilities.hpp>
32 #include <boost/container/allocator_traits.hpp>
33 #include <boost/core/no_exceptions_support.hpp>
34 #include <boost/move/adl_move_swap.hpp>
35 #include <boost/intrusive/detail/minimal_less_equal_header.hpp> //std::less
36 #include <boost/container/detail/placement_new.hpp>
37
38 namespace boost {
39 namespace interprocess {
40 namespace ipcdetail{
41
42 template<class T, class VoidAllocator, class Deleter>
43 class weak_count;
44
45 template<class T, class VoidAllocator, class Deleter>
46 class shared_count
47 {
48 public:
49
50 typedef typename boost::container::
51 allocator_traits<VoidAllocator>::pointer void_ptr;
52 typedef typename boost::intrusive::
53 pointer_traits<void_ptr>::template
54 rebind_pointer<T>::type pointer;
55
56 private:
57 typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
58
59 typedef typename boost::intrusive::
60 pointer_traits<void_ptr>::template
61 rebind_pointer<counted_impl>::type counted_impl_ptr;
62 typedef typename boost::intrusive::
63 pointer_traits<void_ptr>::template
64 rebind_pointer<sp_counted_base>::type counted_base_ptr;
65
66 typedef boost::container::allocator_traits<VoidAllocator> vallocator_traits;
67
68 typedef typename vallocator_traits::template
69 portable_rebind_alloc<counted_impl>::type counted_impl_allocator;
70
71 typedef typename boost::intrusive::
72 pointer_traits<void_ptr>::template
73 rebind_pointer<const Deleter>::type const_deleter_pointer;
74
75 typedef typename boost::intrusive::
76 pointer_traits<void_ptr>::template
77 rebind_pointer<const VoidAllocator>::type const_allocator_pointer;
78
79 pointer m_px;
80 counted_impl_ptr m_pi;
81
82 template <class T2, class VoidAllocator2, class Deleter2>
83 friend class weak_count;
84
85 template <class T2, class VoidAllocator2, class Deleter2>
86 friend class shared_count;
87
88 public:
89
90 shared_count()
91 : m_px(0), m_pi(0) // nothrow
92 {}
93
94 template <class Ptr>
95 shared_count(const shared_count &other_shared_count, const Ptr &p)
96 : m_px(p), m_pi(other_shared_count.m_pi)
97 {}
98
99 template <class Ptr>
100 shared_count(const Ptr &p, const VoidAllocator &a, Deleter d)
101 : m_px(p), m_pi(0)
102 {
103 BOOST_TRY{
104 if(p){
105 counted_impl_allocator alloc(a);
106 m_pi = alloc.allocate(1);
107 //Anti-exception deallocator
108 scoped_ptr<counted_impl,
109 scoped_ptr_dealloc_functor<counted_impl_allocator> >
110 deallocator(m_pi, alloc);
111 //It's more correct to use VoidAllocator::construct but
112 //this needs copy constructor and we don't like it
113 ::new(ipcdetail::to_raw_pointer(m_pi), boost_container_new_t())counted_impl(p, a, d);
114 deallocator.release();
115 }
116 }
117 BOOST_CATCH (...){
118 d(p); // delete p
119 BOOST_RETHROW
120 }
121 BOOST_CATCH_END
122 }
123
124 ~shared_count() // nothrow
125 {
126 if(m_pi)
127 m_pi->release();
128 }
129
130 shared_count(shared_count const & r)
131 : m_px(r.m_px), m_pi(r.m_pi) // nothrow
132 { if( m_pi != 0 ) m_pi->add_ref_copy(); }
133
134 //this is a test
135 template<class Y>
136 explicit shared_count(shared_count<Y, VoidAllocator, Deleter> const & r)
137 : m_px(r.m_px), m_pi(r.m_pi) // nothrow
138 { if( m_pi != 0 ) m_pi->add_ref_copy(); }
139
140 //this is a test
141 template<class Y>
142 explicit shared_count(const pointer & ptr, shared_count<Y, VoidAllocator, Deleter> const & r)
143 : m_px(ptr), m_pi(r.m_pi) // nothrow
144 { if( m_pi != 0 ) m_pi->add_ref_copy(); }
145
146 /*
147 explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
148 // throws bad_weak_ptr when r.use_count() == 0
149 : m_pi( r.m_pi )
150 {
151 if( m_pi == 0 || !m_pi->add_ref_lock() ){
152 boost::throw_exception( boost::interprocess::bad_weak_ptr() );
153 }
154 }
155 */
156 template<class Y>
157 explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
158 // throws bad_weak_ptr when r.use_count() == 0
159 : m_px(r.m_px), m_pi( r.m_pi )
160 {
161 if( m_pi == 0 || !m_pi->add_ref_lock() ){
162 throw( boost::interprocess::bad_weak_ptr() );
163 }
164 }
165
166 const pointer &to_raw_pointer() const
167 { return m_px; }
168
169 pointer &to_raw_pointer()
170 { return m_px; }
171
172 shared_count & operator= (shared_count const & r) // nothrow
173 {
174 m_px = r.m_px;
175 counted_impl_ptr tmp = r.m_pi;
176 if( tmp != m_pi ){
177 if(tmp != 0) tmp->add_ref_copy();
178 if(m_pi != 0) m_pi->release();
179 m_pi = tmp;
180 }
181 return *this;
182 }
183
184 template<class Y>
185 shared_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow
186 {
187 m_px = r.m_px;
188 counted_impl_ptr tmp = r.m_pi;
189 if( tmp != m_pi ){
190 if(tmp != 0) tmp->add_ref_copy();
191 if(m_pi != 0) m_pi->release();
192 m_pi = tmp;
193 }
194 return *this;
195 }
196
197 void swap(shared_count & r) // nothrow
198 { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); }
199
200 long use_count() const // nothrow
201 { return m_pi != 0? m_pi->use_count(): 0; }
202
203 bool unique() const // nothrow
204 { return use_count() == 1; }
205
206 const_deleter_pointer get_deleter() const
207 { return m_pi ? m_pi->get_deleter() : 0; }
208
209 // const_allocator_pointer get_allocator() const
210 // { return m_pi ? m_pi->get_allocator() : 0; }
211
212 template<class T2, class VoidAllocator2, class Deleter2>
213 bool internal_equal (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
214 { return this->m_pi == other.m_pi; }
215
216 template<class T2, class VoidAllocator2, class Deleter2>
217 bool internal_less (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
218 { return std::less<counted_base_ptr>()(this->m_pi, other.m_pi); }
219 };
220
221 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
222 bool operator==(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
223 { return a.internal_equal(b); }
224
225 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
226 bool operator<(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
227 { return a.internal_less(b); }
228
229
230 template<class T, class VoidAllocator, class Deleter>
231 class weak_count
232 {
233 public:
234 typedef typename boost::container::
235 allocator_traits<VoidAllocator>::pointer void_ptr;
236 typedef typename boost::intrusive::
237 pointer_traits<void_ptr>::template
238 rebind_pointer<T>::type pointer;
239
240 private:
241
242 typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
243
244 typedef typename boost::intrusive::
245 pointer_traits<void_ptr>::template
246 rebind_pointer<counted_impl>::type counted_impl_ptr;
247 typedef typename boost::intrusive::
248 pointer_traits<void_ptr>::template
249 rebind_pointer<sp_counted_base>::type counted_base_ptr;
250
251 pointer m_px;
252 counted_impl_ptr m_pi;
253
254 template <class T2, class VoidAllocator2, class Deleter2>
255 friend class weak_count;
256
257 template <class T2, class VoidAllocator2, class Deleter2>
258 friend class shared_count;
259
260 public:
261
262 weak_count(): m_px(0), m_pi(0) // nothrow
263 {}
264
265 template <class Y>
266 explicit weak_count(shared_count<Y, VoidAllocator, Deleter> const & r)
267 : m_px(r.m_px), m_pi(r.m_pi) // nothrow
268 { if(m_pi != 0) m_pi->weak_add_ref(); }
269
270 weak_count(weak_count const & r)
271 : m_px(r.m_px), m_pi(r.m_pi) // nothrow
272 { if(m_pi != 0) m_pi->weak_add_ref(); }
273
274 template<class Y>
275 weak_count(weak_count<Y, VoidAllocator, Deleter> const & r)
276 : m_px(r.m_px), m_pi(r.m_pi) // nothrow
277 { if(m_pi != 0) m_pi->weak_add_ref(); }
278
279 ~weak_count() // nothrow
280 { if(m_pi != 0) m_pi->weak_release(); }
281
282 template<class Y>
283 weak_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow
284 {
285 m_px = r.m_px;
286 counted_impl_ptr tmp = r.m_pi;
287 if(tmp != 0) tmp->weak_add_ref();
288 if(m_pi != 0) m_pi->weak_release();
289 m_pi = tmp;
290 return *this;
291 }
292
293 weak_count & operator= (weak_count const & r) // nothrow
294 {
295 m_px = r.m_px;
296 counted_impl_ptr tmp = r.m_pi;
297 if(tmp != 0) tmp->weak_add_ref();
298 if(m_pi != 0) m_pi->weak_release();
299 m_pi = tmp;
300 return *this;
301 }
302
303 void set_pointer(const pointer &ptr)
304 { m_px = ptr; }
305
306 template<class Y>
307 weak_count & operator= (weak_count<Y, VoidAllocator, Deleter> const& r) // nothrow
308 {
309 counted_impl_ptr tmp = r.m_pi;
310 if(tmp != 0) tmp->weak_add_ref();
311 if(m_pi != 0) m_pi->weak_release();
312 m_pi = tmp;
313 return *this;
314 }
315
316 void swap(weak_count & r) // nothrow
317 { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); }
318
319 long use_count() const // nothrow
320 { return m_pi != 0? m_pi->use_count() : 0; }
321
322 template<class T2, class VoidAllocator2, class Deleter2>
323 bool internal_equal (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
324 { return this->m_pi == other.m_pi; }
325
326 template<class T2, class VoidAllocator2, class Deleter2>
327 bool internal_less (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
328 { return std::less<counted_base_ptr>()(this->m_pi, other.m_pi); }
329 };
330
331 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
332 bool operator==(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
333 { return a.internal_equal(b); }
334
335 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
336 bool operator<(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
337 { return a.internal_less(b); }
338
339 } // namespace ipcdetail
340 } // namespace interprocess
341 } // namespace boost
342
343
344 #include <boost/interprocess/detail/config_end.hpp>
345
346
347 #endif // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED