]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/interprocess/smart_ptr/shared_ptr.hpp
update sources to v12.2.3
[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> *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::intrusive::
107 pointer_traits<typename VoidAllocator::pointer>::template
108 rebind_pointer<T>::type pointer;
109 typedef typename ipcdetail::add_reference
110 <value_type>::type reference;
111 typedef typename ipcdetail::add_reference
112 <const value_type>::type const_reference;
113 typedef typename boost::intrusive::
114 pointer_traits<typename VoidAllocator::pointer>::template
115 rebind_pointer<const Deleter>::type const_deleter_pointer;
116 typedef typename boost::intrusive::
117 pointer_traits<typename VoidAllocator::pointer>::template
118 rebind_pointer<const VoidAllocator>::type const_allocator_pointer;
119
120 BOOST_COPYABLE_AND_MOVABLE(shared_ptr)
121 public:
122
123 //!Constructs an empty shared_ptr.
124 //!Use_count() == 0 && get()== 0.
125 shared_ptr()
126 : m_pn() // never throws
127 {}
128
129 //!Constructs a shared_ptr that owns the pointer p. Auxiliary data will be allocated
130 //!with a copy of a and the object will be deleted with a copy of d.
131 //!Requirements: Deleter and A's copy constructor must not throw.
132 explicit shared_ptr(const pointer&p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
133 : m_pn(p, a, d)
134 {
135 //Check that the pointer passed is of the same type that
136 //the pointer the allocator defines or it's a raw pointer
137 typedef typename boost::intrusive::
138 pointer_traits<pointer>::template
139 rebind_pointer<T>::type ParameterPointer;
140
141 BOOST_STATIC_ASSERT((ipcdetail::is_same<pointer, ParameterPointer>::value) ||
142 (ipcdetail::is_pointer<pointer>::value));
143 ipcdetail::sp_enable_shared_from_this<T, VoidAllocator, Deleter>( m_pn, ipcdetail::to_raw_pointer(p), ipcdetail::to_raw_pointer(p) );
144 }
145
146 //!Copy constructs a shared_ptr. If r is empty, constructs an empty shared_ptr. Otherwise, constructs
147 //!a shared_ptr that shares ownership with r. Never throws.
148 shared_ptr(const shared_ptr &r)
149 : m_pn(r.m_pn) // never throws
150 {}
151
152 //!Constructs a shared_ptr that shares ownership with other and stores p.
153 //!Postconditions: get() == p && use_count() == r.use_count().
154 //!Throws: nothing.
155 shared_ptr(const shared_ptr &other, const pointer &p)
156 : m_pn(other.m_pn, p)
157 {}
158
159 //!If r is empty, constructs an empty shared_ptr. Otherwise, constructs
160 //!a shared_ptr that shares ownership with r. Never throws.
161 template<class Y>
162 shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r)
163 : m_pn(r.m_pn) // never throws
164 {}
165
166 //!Constructs a shared_ptr that shares ownership with r and stores
167 //!a copy of the pointer stored in r.
168 template<class Y>
169 explicit shared_ptr(weak_ptr<Y, VoidAllocator, Deleter> const & r)
170 : m_pn(r.m_pn) // may throw
171 {}
172
173 //!Move-Constructs a shared_ptr that takes ownership of other resource and
174 //!other is put in default-constructed state.
175 //!Throws: nothing.
176 explicit shared_ptr(BOOST_RV_REF(shared_ptr) other)
177 : m_pn()
178 { this->swap(other); }
179
180 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
181 template<class Y>
182 shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::static_cast_tag)
183 : m_pn( pointer(static_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
184 , r.m_pn)
185 {}
186
187 template<class Y>
188 shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::const_cast_tag)
189 : m_pn( pointer(const_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
190 , r.m_pn)
191 {}
192
193 template<class Y>
194 shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::dynamic_cast_tag)
195 : m_pn( pointer(dynamic_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
196 , r.m_pn)
197 {
198 if(!m_pn.to_raw_pointer()){ // need to allocate new counter -- the cast failed
199 m_pn = ipcdetail::shared_count<T, VoidAllocator, Deleter>();
200 }
201 }
202 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
203
204 //!Equivalent to shared_ptr(r).swap(*this).
205 //!Never throws
206 template<class Y>
207 shared_ptr & operator=(shared_ptr<Y, VoidAllocator, Deleter> const & r)
208 {
209 m_pn = r.m_pn; // shared_count::op= doesn't throw
210 return *this;
211 }
212
213 //!Equivalent to shared_ptr(r).swap(*this).
214 //!Never throws
215 shared_ptr & operator=(BOOST_COPY_ASSIGN_REF(shared_ptr) r)
216 {
217 m_pn = r.m_pn; // shared_count::op= doesn't throw
218 return *this;
219 }
220
221 //!Move-assignment. Equivalent to shared_ptr(other).swap(*this).
222 //!Never throws
223 shared_ptr & operator=(BOOST_RV_REF(shared_ptr) other) // never throws
224 {
225 this_type(other).swap(*this);
226 return *this;
227 }
228
229 //!This is equivalent to:
230 //!this_type().swap(*this);
231 void reset()
232 {
233 this_type().swap(*this);
234 }
235
236 //!This is equivalent to:
237 //!this_type(p, a, d).swap(*this);
238 template<class Pointer>
239 void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
240 {
241 //Check that the pointer passed is of the same type that
242 //the pointer the allocator defines or it's a raw pointer
243 typedef typename boost::intrusive::
244 pointer_traits<Pointer>::template
245 rebind_pointer<T>::type ParameterPointer;
246 BOOST_STATIC_ASSERT((ipcdetail::is_same<pointer, ParameterPointer>::value) ||
247 (ipcdetail::is_pointer<Pointer>::value));
248 this_type(p, a, d).swap(*this);
249 }
250
251 template<class Y>
252 void reset(shared_ptr<Y, VoidAllocator, Deleter> const & r, const pointer &p)
253 {
254 this_type(r, p).swap(*this);
255 }
256
257 //!Returns a reference to the
258 //!pointed type
259 reference operator* () const // never throws
260 { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return *m_pn.to_raw_pointer(); }
261
262 //!Returns the pointer pointing
263 //!to the owned object
264 pointer operator-> () const // never throws
265 { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return m_pn.to_raw_pointer(); }
266
267 //!Returns the pointer pointing
268 //!to the owned object
269 pointer get() const // never throws
270 { return m_pn.to_raw_pointer(); }
271
272 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
273 // implicit conversion to "bool"
274 void unspecified_bool_type_func() const {}
275 typedef void (this_type::*unspecified_bool_type)() const;
276
277 operator unspecified_bool_type() const // never throws
278 { return !m_pn.to_raw_pointer() ? 0 : &this_type::unspecified_bool_type_func; }
279 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
280
281 //!Not operator.
282 //!Returns true if this->get() != 0, false otherwise
283 bool operator! () const // never throws
284 { return !m_pn.to_raw_pointer(); }
285
286 //!Returns use_count() == 1.
287 //!unique() might be faster than use_count()
288 bool unique() const // never throws
289 { return m_pn.unique(); }
290
291 //!Returns the number of shared_ptr objects, *this included,
292 //!that share ownership with *this, or an unspecified nonnegative
293 //!value when *this is empty.
294 //!use_count() is not necessarily efficient. Use only for
295 //!debugging and testing purposes, not for production code.
296 long use_count() const // never throws
297 { return m_pn.use_count(); }
298
299 //!Exchanges the contents of the two
300 //!smart pointers.
301 void swap(shared_ptr<T, VoidAllocator, Deleter> & other) // never throws
302 { m_pn.swap(other.m_pn); }
303
304 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
305
306 template<class T2, class A2, class Deleter2>
307 bool _internal_less(shared_ptr<T2, A2, Deleter2> const & rhs) const
308 { return m_pn < rhs.m_pn; }
309
310 const_deleter_pointer get_deleter() const
311 { return m_pn.get_deleter(); }
312
313 // const_allocator_pointer get_allocator() const
314 // { return m_pn.get_allocator(); }
315
316 private:
317
318 template<class T2, class A2, class Deleter2> friend class shared_ptr;
319 template<class T2, class A2, class Deleter2> friend class weak_ptr;
320
321 ipcdetail::shared_count<T, VoidAllocator, Deleter> m_pn; // reference counter
322 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
323 }; // shared_ptr
324
325 template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
326 bool operator==(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
327 { return a.get() == b.get(); }
328
329 template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
330 bool operator!=(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
331 { return a.get() != b.get(); }
332
333 template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
334 bool operator<(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
335 { return a._internal_less(b); }
336
337 template<class T, class VoidAllocator, class Deleter> inline
338 void swap(shared_ptr<T, VoidAllocator, Deleter> & a, shared_ptr<T, VoidAllocator, Deleter> & b)
339 { a.swap(b); }
340
341 template<class T, class VoidAllocator, class Deleter, class U> inline
342 shared_ptr<T, VoidAllocator, Deleter> static_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
343 { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::static_cast_tag()); }
344
345 template<class T, class VoidAllocator, class Deleter, class U> inline
346 shared_ptr<T, VoidAllocator, Deleter> const_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
347 { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::const_cast_tag()); }
348
349 template<class T, class VoidAllocator, class Deleter, class U> inline
350 shared_ptr<T, VoidAllocator, Deleter> dynamic_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
351 { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::dynamic_cast_tag()); }
352
353 // to_raw_pointer() enables boost::mem_fn to recognize shared_ptr
354 template<class T, class VoidAllocator, class Deleter> inline
355 T * to_raw_pointer(shared_ptr<T, VoidAllocator, Deleter> const & p)
356 { return p.get(); }
357
358 // operator<<
359 template<class E, class T, class Y, class VoidAllocator, class Deleter> inline
360 std::basic_ostream<E, T> & operator<<
361 (std::basic_ostream<E, T> & os, shared_ptr<Y, VoidAllocator, Deleter> const & p)
362 { os << p.get(); return os; }
363
364 //!Returns the type of a shared pointer
365 //!of type T with the allocator boost::interprocess::allocator allocator
366 //!and boost::interprocess::deleter deleter
367 //!that can be constructed in the given managed segment type.
368 template<class T, class ManagedMemory>
369 struct managed_shared_ptr
370 {
371 typedef typename ManagedMemory::template allocator<void>::type void_allocator;
372 typedef typename ManagedMemory::template deleter<T>::type deleter;
373 typedef shared_ptr< T, void_allocator, deleter> type;
374 };
375
376 //!Returns an instance of a shared pointer constructed
377 //!with the default allocator and deleter from a pointer
378 //!of type T that has been allocated in the passed managed segment
379 template<class T, class ManagedMemory>
380 inline typename managed_shared_ptr<T, ManagedMemory>::type
381 make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory)
382 {
383 return typename managed_shared_ptr<T, ManagedMemory>::type
384 ( constructed_object
385 , managed_memory.template get_allocator<void>()
386 , managed_memory.template get_deleter<T>()
387 );
388 }
389
390 //!Returns an instance of a shared pointer constructed
391 //!with the default allocator and deleter from a pointer
392 //!of type T that has been allocated in the passed managed segment.
393 //!Does not throw, return null shared pointer in error.
394 template<class T, class ManagedMemory>
395 inline typename managed_shared_ptr<T, ManagedMemory>::type
396 make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory, const std::nothrow_t &)
397 {
398 try{
399 return typename managed_shared_ptr<T, ManagedMemory>::type
400 ( constructed_object
401 , managed_memory.template get_allocator<void>()
402 , managed_memory.template get_deleter<T>()
403 );
404 }
405 catch(...){
406 return typename managed_shared_ptr<T, ManagedMemory>::type();
407 }
408 }
409
410
411 } // namespace interprocess
412
413 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
414
415 #if defined(_MSC_VER) && (_MSC_VER < 1400)
416 // to_raw_pointer() enables boost::mem_fn to recognize shared_ptr
417 template<class T, class VoidAllocator, class Deleter> inline
418 T * to_raw_pointer(boost::interprocess::shared_ptr<T, VoidAllocator, Deleter> const & p)
419 { return p.get(); }
420 #endif
421
422 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
423
424 } // namespace boost
425
426 #include <boost/interprocess/detail/config_end.hpp>
427
428 #endif // #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED