PageRenderTime 46ms CodeModel.GetById 8ms app.highlight 34ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/interprocess/smart_ptr/shared_ptr.hpp

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