• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
sp_enable_shared_from_this(shared_count<T,VoidAllocator,Deleter> const & pn,enable_shared_from_this<T,VoidAllocator,Deleter> * pe,T * ptr)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>
sp_enable_shared_from_this(shared_count<T,VoidAllocator,Deleter> const &,...)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.
shared_ptr()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.
shared_ptr(const pointer & p,const VoidAllocator & a=VoidAllocator (),const Deleter & d=Deleter ())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.
shared_ptr(const shared_ptr & r)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.
shared_ptr(const shared_ptr & other,const pointer & p)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>
shared_ptr(shared_ptr<Y,VoidAllocator,Deleter> const & r)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>
shared_ptr(weak_ptr<Y,VoidAllocator,Deleter> const & r)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.
shared_ptr(BOOST_RV_REF (shared_ptr)other)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>
shared_ptr(shared_ptr<Y,VoidAllocator,Deleter> const & r,ipcdetail::static_cast_tag)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>
shared_ptr(shared_ptr<Y,VoidAllocator,Deleter> const & r,ipcdetail::const_cast_tag)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>
shared_ptr(shared_ptr<Y,VoidAllocator,Deleter> const & r,ipcdetail::dynamic_cast_tag)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>
operator =(shared_ptr<Y,VoidAllocator,Deleter> const & r)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
operator =(BOOST_COPY_ASSIGN_REF (shared_ptr)r)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
operator =(BOOST_RV_REF (shared_ptr)other)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);
reset()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>
reset(const Pointer & p,const VoidAllocator & a=VoidAllocator (),const Deleter & d=Deleter ())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>
reset(shared_ptr<Y,VoidAllocator,Deleter> const & r,const pointer & p)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
operator *() const259    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
operator ->() const264    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
get() const269    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"
unspecified_bool_type_func() const274    void unspecified_bool_type_func() const {}
275    typedef void (this_type::*unspecified_bool_type)() const;
276 
operator unspecified_bool_type() const277    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
operator !() const283    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()
unique() const288    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.
use_count() const296    long use_count() const // never throws
297    {  return m_pn.use_count();  }
298 
299    //!Exchanges the contents of the two
300    //!smart pointers.
swap(shared_ptr<T,VoidAllocator,Deleter> & other)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>
_internal_less(shared_ptr<T2,A2,Deleter2> const & rhs) const307    bool _internal_less(shared_ptr<T2, A2, Deleter2> const & rhs) const
308    {  return m_pn < rhs.m_pn;  }
309 
get_deleter() const310    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
operator ==(shared_ptr<T,VoidAllocator,Deleter> const & a,shared_ptr<U,VoidAllocator2,Deleter2> const & b)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
operator !=(shared_ptr<T,VoidAllocator,Deleter> const & a,shared_ptr<U,VoidAllocator2,Deleter2> const & b)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
operator <(shared_ptr<T,VoidAllocator,Deleter> const & a,shared_ptr<U,VoidAllocator2,Deleter2> const & b)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
swap(shared_ptr<T,VoidAllocator,Deleter> & a,shared_ptr<T,VoidAllocator,Deleter> & b)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
static_pointer_cast(shared_ptr<U,VoidAllocator,Deleter> const & r)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
const_pointer_cast(shared_ptr<U,VoidAllocator,Deleter> const & r)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
dynamic_pointer_cast(shared_ptr<U,VoidAllocator,Deleter> const & r)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
to_raw_pointer(shared_ptr<T,VoidAllocator,Deleter> const & p)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
operator <<(std::basic_ostream<E,T> & os,shared_ptr<Y,VoidAllocator,Deleter> const & p)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
make_managed_shared_ptr(T * constructed_object,ManagedMemory & managed_memory)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
make_managed_shared_ptr(T * constructed_object,ManagedMemory & managed_memory,const std::nothrow_t &)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
to_raw_pointer(boost::interprocess::shared_ptr<T,VoidAllocator,Deleter> const & p)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
429