]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/interprocess/smart_ptr/shared_ptr.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / interprocess / smart_ptr / shared_ptr.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // This file is the adaptation for Interprocess of boost/shared_ptr.hpp
4 //
5 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
6 // (C) Copyright Peter Dimov 2001, 2002, 2003
7 // (C) Copyright Ion Gaztanaga 2006-2012.
8 // Distributed under the Boost Software License, Version 1.0.
9 // (See accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
11 //
12 // See http://www.boost.org/libs/interprocess for documentation.
13 //
14 //////////////////////////////////////////////////////////////////////////////
15
16 #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED
17 #define BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED
18
19 #ifndef BOOST_CONFIG_HPP
20 # include <boost/config.hpp>
21 #endif
22 #
23 #if defined(BOOST_HAS_PRAGMA_ONCE)
24 # pragma once
25 #endif
26
27 #include <boost/interprocess/detail/config_begin.hpp>
28 #include <boost/interprocess/detail/workaround.hpp>
29
30 #include <boost/interprocess/detail/utilities.hpp>
31 #include <boost/interprocess/detail/cast_tags.hpp>
32 #include <boost/assert.hpp>
33 #include <boost/interprocess/smart_ptr/detail/shared_count.hpp>
34 #include <boost/interprocess/detail/mpl.hpp>
35 #include <boost/interprocess/detail/nothrow.hpp>
36 #include <boost/move/utility_core.hpp>
37 #include <boost/interprocess/detail/type_traits.hpp>
38 #include <boost/interprocess/allocators/allocator.hpp>
39 #include <boost/interprocess/smart_ptr/deleter.hpp>
40 #include <boost/static_assert.hpp>
41 #include <boost/intrusive/pointer_traits.hpp>
42
43 #include <iosfwd> // for std::basic_ostream
44
45 //!\file
46 //!Describes the smart pointer shared_ptr
47
48 namespace boost{
49 namespace interprocess{
50
51 template<class T, class VoidAllocator, class Deleter> class weak_ptr;
52 template<class T, class VoidAllocator, class Deleter> class enable_shared_from_this;
53
54 namespace ipcdetail{
55
56 template<class T, class VoidAllocator, class Deleter>
57 inline void sp_enable_shared_from_this
58 (shared_count<T, VoidAllocator, Deleter> const & pn
59 ,enable_shared_from_this<T, VoidAllocator, Deleter> const*pe
60 ,T *ptr)
61
62 {
63 (void)ptr;
64 if(pe != 0){
65 pe->_internal_weak_this._internal_assign(pn);
66 }
67 }
68
69 template<class T, class VoidAllocator, class Deleter>
70 inline void sp_enable_shared_from_this(shared_count<T, VoidAllocator, Deleter> const &, ...)
71 {}
72
73 } // namespace ipcdetail
74
75 //!shared_ptr stores a pointer to a dynamically allocated object.
76 //!The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to
77 //!it is destroyed or reset.
78 //!
79 //!shared_ptr is parameterized on
80 //!T (the type of the object pointed to), VoidAllocator (the void allocator to be used
81 //!to allocate the auxiliary data) and Deleter (the deleter whose
82 //!operator() will be used to delete the object.
83 //!
84 //!The internal pointer will be of the same pointer type as typename
85 //!VoidAllocator::pointer type (that is, if typename VoidAllocator::pointer is
86 //!offset_ptr<void>, the internal pointer will be offset_ptr<T>).
87 //!
88 //!Because the implementation uses reference counting, cycles of shared_ptr
89 //!instances will not be reclaimed. For example, if main() holds a
90 //!shared_ptr to A, which directly or indirectly holds a shared_ptr back
91 //!to A, A's use count will be 2. Destruction of the original shared_ptr
92 //!will leave A dangling with a use count of 1.
93 //!Use weak_ptr to "break cycles."
94 template<class T, class VoidAllocator, class Deleter>
95 class shared_ptr
96 {
97 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
98 private:
99 typedef shared_ptr<T, VoidAllocator, Deleter> this_type;
100 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
101
102 public:
103
104 typedef T element_type;
105 typedef T value_type;
106 typedef typename boost::container::
107 allocator_traits<VoidAllocator>::pointer void_ptr;
108 typedef typename boost::intrusive::
109 pointer_traits<void_ptr>::template
110 rebind_pointer<T>::type pointer;
111 typedef typename ipcdetail::add_reference
112 <value_type>::type reference;
113 typedef typename ipcdetail::add_reference
114 <const value_type>::type const_reference;
115 typedef typename boost::intrusive::
116 pointer_traits<void_ptr>::template
117 rebind_pointer<const Deleter>::type const_deleter_pointer;
118 typedef typename boost::intrusive::
119 pointer_traits<void_ptr>::template
120 rebind_pointer<const VoidAllocator>::type const_allocator_pointer;
121
122 BOOST_COPYABLE_AND_MOVABLE(shared_ptr)
123 public:
124
125 //!Constructs an empty shared_ptr.
126 //!Use_count() == 0 && get()== 0.
127 shared_ptr()
128 : m_pn() // never throws
129 {}
130
131 //!Constructs a shared_ptr that owns the pointer p. Auxiliary data will be allocated
132 //!with a copy of a and the object will be deleted with a copy of d.
133 //!Requirements: Deleter and A's copy constructor must not throw.
134 explicit shared_ptr(const pointer&p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
135 : m_pn(p, a, d)
136 {
137 //Check that the pointer passed is of the same type that
138 //the pointer the allocator defines or it's a raw pointer
139 typedef typename boost::intrusive::
140 pointer_traits<pointer>::template
141 rebind_pointer<T>::type ParameterPointer;
142
143 BOOST_STATIC_ASSERT((ipcdetail::is_same<pointer, ParameterPointer>::value) ||
144 (ipcdetail::is_pointer<pointer>::value));
145 ipcdetail::sp_enable_shared_from_this<T, VoidAllocator, Deleter>( m_pn, ipcdetail::to_raw_pointer(p), ipcdetail::to_raw_pointer(p) );
146 }
147
148 //!Copy constructs a shared_ptr. If r is empty, constructs an empty shared_ptr. Otherwise, constructs
149 //!a shared_ptr that shares ownership with r. Never throws.
150 shared_ptr(const shared_ptr &r)
151 : m_pn(r.m_pn) // never throws
152 {}
153
154 //!Constructs a shared_ptr that shares ownership with other and stores p.
155 //!Postconditions: get() == p && use_count() == r.use_count().
156 //!Throws: nothing.
157 shared_ptr(const shared_ptr &other, const pointer &p)
158 : m_pn(other.m_pn, p)
159 {}
160
161 //!If r is empty, constructs an empty shared_ptr. Otherwise, constructs
162 //!a shared_ptr that shares ownership with r. Never throws.
163 template<class Y>
164 shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r)
165 : m_pn(r.m_pn) // never throws
166 {}
167
168 //!Constructs a shared_ptr that shares ownership with r and stores
169 //!a copy of the pointer stored in r.
170 template<class Y>
171 explicit shared_ptr(weak_ptr<Y, VoidAllocator, Deleter> const & r)
172 : m_pn(r.m_pn) // may throw
173 {}
174
175 //!Move-Constructs a shared_ptr that takes ownership of other resource and
176 //!other is put in default-constructed state.
177 //!Throws: nothing.
178 explicit shared_ptr(BOOST_RV_REF(shared_ptr) other)
179 : m_pn()
180 { this->swap(other); }
181
182 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
183 template<class Y>
184 shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::static_cast_tag)
185 : m_pn( pointer(static_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
186 , r.m_pn)
187 {}
188
189 template<class Y>
190 shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::const_cast_tag)
191 : m_pn( pointer(const_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
192 , r.m_pn)
193 {}
194
195 template<class Y>
196 shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::dynamic_cast_tag)
197 : m_pn( pointer(dynamic_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
198 , r.m_pn)
199 {
200 if(!m_pn.to_raw_pointer()){ // need to allocate new counter -- the cast failed
201 m_pn = ipcdetail::shared_count<T, VoidAllocator, Deleter>();
202 }
203 }
204 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
205
206 //!Equivalent to shared_ptr(r).swap(*this).
207 //!Never throws
208 template<class Y>
209 shared_ptr & operator=(shared_ptr<Y, VoidAllocator, Deleter> const & r)
210 {
211 m_pn = r.m_pn; // shared_count::op= doesn't throw
212 return *this;
213 }
214
215 //!Equivalent to shared_ptr(r).swap(*this).
216 //!Never throws
217 shared_ptr & operator=(BOOST_COPY_ASSIGN_REF(shared_ptr) r)
218 {
219 m_pn = r.m_pn; // shared_count::op= doesn't throw
220 return *this;
221 }
222
223 //!Move-assignment. Equivalent to shared_ptr(other).swap(*this).
224 //!Never throws
225 shared_ptr & operator=(BOOST_RV_REF(shared_ptr) other) // never throws
226 {
227 this_type(other).swap(*this);
228 return *this;
229 }
230
231 //!This is equivalent to:
232 //!this_type().swap(*this);
233 void reset()
234 {
235 this_type().swap(*this);
236 }
237
238 //!This is equivalent to:
239 //!this_type(p, a, d).swap(*this);
240 template<class Pointer>
241 void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
242 {
243 //Check that the pointer passed is of the same type that
244 //the pointer the allocator defines or it's a raw pointer
245 typedef typename boost::intrusive::
246 pointer_traits<Pointer>::template
247 rebind_pointer<T>::type ParameterPointer;
248 BOOST_STATIC_ASSERT((ipcdetail::is_same<pointer, ParameterPointer>::value) ||
249 (ipcdetail::is_pointer<Pointer>::value));
250 this_type(p, a, d).swap(*this);
251 }
252
253 template<class Y>
254 void reset(shared_ptr<Y, VoidAllocator, Deleter> const & r, const pointer &p)
255 {
256 this_type(r, p).swap(*this);
257 }
258
259 //!Returns a reference to the
260 //!pointed type
261 reference operator* () const // never throws
262 { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return *m_pn.to_raw_pointer(); }
263
264 //!Returns the pointer pointing
265 //!to the owned object
266 pointer operator-> () const // never throws
267 { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return m_pn.to_raw_pointer(); }
268
269 //!Returns the pointer pointing
270 //!to the owned object
271 pointer get() const // never throws
272 { return m_pn.to_raw_pointer(); }
273
274 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
275 // implicit conversion to "bool"
276 void unspecified_bool_type_func() const {}
277 typedef void (this_type::*unspecified_bool_type)() const;
278
279 operator unspecified_bool_type() const // never throws
280 { return !m_pn.to_raw_pointer() ? 0 : &this_type::unspecified_bool_type_func; }
281 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
282
283 //!Not operator.
284 //!Returns true if this->get() != 0, false otherwise
285 bool operator! () const // never throws
286 { return !m_pn.to_raw_pointer(); }
287
288 //!Returns use_count() == 1.
289 //!unique() might be faster than use_count()
290 bool unique() const // never throws
291 { return m_pn.unique(); }
292
293 //!Returns the number of shared_ptr objects, *this included,
294 //!that share ownership with *this, or an unspecified nonnegative
295 //!value when *this is empty.
296 //!use_count() is not necessarily efficient. Use only for
297 //!debugging and testing purposes, not for production code.
298 long use_count() const // never throws
299 { return m_pn.use_count(); }
300
301 //!Exchanges the contents of the two
302 //!smart pointers.
303 void swap(shared_ptr<T, VoidAllocator, Deleter> & other) // never throws
304 { m_pn.swap(other.m_pn); }
305
306 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
307
308 template<class T2, class A2, class Deleter2>
309 bool _internal_less(shared_ptr<T2, A2, Deleter2> const & rhs) const
310 { return m_pn < rhs.m_pn; }
311
312 const_deleter_pointer get_deleter() const
313 { return m_pn.get_deleter(); }
314
315 // const_allocator_pointer get_allocator() const
316 // { return m_pn.get_allocator(); }
317
318 private:
319
320 template<class T2, class A2, class Deleter2> friend class shared_ptr;
321 template<class T2, class A2, class Deleter2> friend class weak_ptr;
322
323 ipcdetail::shared_count<T, VoidAllocator, Deleter> m_pn; // reference counter
324 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
325 }; // shared_ptr
326
327 template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
328 bool operator==(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
329 { return a.get() == b.get(); }
330
331 template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
332 bool operator!=(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
333 { return a.get() != b.get(); }
334
335 template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
336 bool operator<(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
337 { return a._internal_less(b); }
338
339 template<class T, class VoidAllocator, class Deleter> inline
340 void swap(shared_ptr<T, VoidAllocator, Deleter> & a, shared_ptr<T, VoidAllocator, Deleter> & b)
341 { a.swap(b); }
342
343 template<class T, class VoidAllocator, class Deleter, class U> inline
344 shared_ptr<T, VoidAllocator, Deleter> static_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
345 { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::static_cast_tag()); }
346
347 template<class T, class VoidAllocator, class Deleter, class U> inline
348 shared_ptr<T, VoidAllocator, Deleter> const_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
349 { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::const_cast_tag()); }
350
351 template<class T, class VoidAllocator, class Deleter, class U> inline
352 shared_ptr<T, VoidAllocator, Deleter> dynamic_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
353 { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::dynamic_cast_tag()); }
354
355 // to_raw_pointer() enables boost::mem_fn to recognize shared_ptr
356 template<class T, class VoidAllocator, class Deleter> inline
357 T * to_raw_pointer(shared_ptr<T, VoidAllocator, Deleter> const & p)
358 { return p.get(); }
359
360 // operator<<
361 template<class E, class T, class Y, class VoidAllocator, class Deleter> inline
362 std::basic_ostream<E, T> & operator<<
363 (std::basic_ostream<E, T> & os, shared_ptr<Y, VoidAllocator, Deleter> const & p)
364 { os << p.get(); return os; }
365
366 //!Returns the type of a shared pointer
367 //!of type T with the allocator boost::interprocess::allocator allocator
368 //!and boost::interprocess::deleter deleter
369 //!that can be constructed in the given managed segment type.
370 template<class T, class ManagedMemory>
371 struct managed_shared_ptr
372 {
373 typedef typename ManagedMemory::template allocator<void>::type void_allocator;
374 typedef typename ManagedMemory::template deleter<T>::type deleter;
375 typedef shared_ptr< T, void_allocator, deleter> type;
376 };
377
378 //!Returns an instance of a shared pointer constructed
379 //!with the default allocator and deleter from a pointer
380 //!of type T that has been allocated in the passed managed segment
381 template<class T, class ManagedMemory>
382 inline typename managed_shared_ptr<T, ManagedMemory>::type
383 make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory)
384 {
385 return typename managed_shared_ptr<T, ManagedMemory>::type
386 ( constructed_object
387 , managed_memory.template get_allocator<void>()
388 , managed_memory.template get_deleter<T>()
389 );
390 }
391
392 //!Returns an instance of a shared pointer constructed
393 //!with the default allocator and deleter from a pointer
394 //!of type T that has been allocated in the passed managed segment.
395 //!Does not throw, return null shared pointer in error.
396 template<class T, class ManagedMemory>
397 inline typename managed_shared_ptr<T, ManagedMemory>::type
398 make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory, const std::nothrow_t &)
399 {
400 BOOST_TRY{
401 return typename managed_shared_ptr<T, ManagedMemory>::type
402 ( constructed_object
403 , managed_memory.template get_allocator<void>()
404 , managed_memory.template get_deleter<T>()
405 );
406 }
407 BOOST_CATCH(...){
408 return typename managed_shared_ptr<T, ManagedMemory>::type();
409 } BOOST_CATCH_END
410 }
411
412
413 } // namespace interprocess
414
415 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
416
417 #if defined(_MSC_VER) && (_MSC_VER < 1400)
418 // to_raw_pointer() enables boost::mem_fn to recognize shared_ptr
419 template<class T, class VoidAllocator, class Deleter> inline
420 T * to_raw_pointer(boost::interprocess::shared_ptr<T, VoidAllocator, Deleter> const & p)
421 { return p.get(); }
422 #endif
423
424 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
425
426 } // namespace boost
427
428 #include <boost/interprocess/detail/config_end.hpp>
429
430 #endif // #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED