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/static_assert.hpp>
34#include <boost/interprocess/smart_ptr/detail/shared_count.hpp>
35#include <boost/interprocess/detail/mpl.hpp>
36#include <boost/interprocess/detail/nothrow.hpp>
37#include <boost/move/utility_core.hpp>
38#include <boost/interprocess/detail/type_traits.hpp>
39#include <boost/interprocess/allocators/allocator.hpp>
40#include <boost/interprocess/smart_ptr/deleter.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
48namespace boost{
49namespace interprocess{
50
51template<class T, class VoidAllocator, class Deleter> class weak_ptr;
52template<class T, class VoidAllocator, class Deleter> class enable_shared_from_this;
53
54namespace ipcdetail{
55
56template<class T, class VoidAllocator, class Deleter>
57inline 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
69template<class T, class VoidAllocator, class Deleter>
70inline 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."
94template<class T, class VoidAllocator, class Deleter>
95class 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(other&: *this);
228 return *this;
229 }
230
231 //!This is equivalent to:
232 //!this_type().swap(*this);
233 void reset()
234 {
235 this_type().swap(other&: *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(other&: *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(other&: *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
327template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
328bool operator==(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
329{ return a.get() == b.get(); }
330
331template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
332bool operator!=(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
333{ return a.get() != b.get(); }
334
335template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
336bool operator<(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
337{ return a._internal_less(b); }
338
339template<class T, class VoidAllocator, class Deleter> inline
340void swap(shared_ptr<T, VoidAllocator, Deleter> & a, shared_ptr<T, VoidAllocator, Deleter> & b)
341{ a.swap(b); }
342
343template<class T, class VoidAllocator, class Deleter, class U> inline
344shared_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
347template<class T, class VoidAllocator, class Deleter, class U> inline
348shared_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
351template<class T, class VoidAllocator, class Deleter, class U> inline
352shared_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
356template<class T, class VoidAllocator, class Deleter> inline
357T * to_raw_pointer(shared_ptr<T, VoidAllocator, Deleter> const & p)
358{ return p.get(); }
359
360// operator<<
361template<class E, class T, class Y, class VoidAllocator, class Deleter> inline
362std::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.
370template<class T, class ManagedMemory>
371struct 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
381template<class T, class ManagedMemory>
382inline 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.
396template<class T, class ManagedMemory>
397inline 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
419template<class T, class VoidAllocator, class Deleter> inline
420T * 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
431

source code of boost/libs/interprocess/include/boost/interprocess/smart_ptr/shared_ptr.hpp