fix doc example typo
[boost.git] / boost / interprocess / smart_ptr / shared_ptr.hpp
blob5d650e2f7b38d7bc9eefa64cfda55c3f6e63a67e
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-2008.
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)
12 // See http://www.boost.org/libs/interprocess for documentation.
14 //////////////////////////////////////////////////////////////////////////////
16 #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED
17 #define BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED
19 #include <boost/interprocess/detail/config_begin.hpp>
20 #include <boost/interprocess/detail/workaround.hpp>
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>
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
39 //!\file
40 //!Describes the smart pointer shared_ptr
42 namespace boost{
43 namespace interprocess{
45 template<class T, class VoidAllocator, class Deleter> class weak_ptr;
46 template<class T, class VoidAllocator, class Deleter> class enable_shared_from_this;
48 namespace detail{
50 template<class T, class VoidAllocator, class Deleter>
51 inline 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)
57 (void)ptr;
58 if(pe != 0){
59 pe->_internal_weak_this._internal_assign(pn);
63 template<class T, class VoidAllocator, class Deleter>
64 inline void sp_enable_shared_from_this(shared_count<T, VoidAllocator, Deleter> const &, ...)
67 } // namespace detail
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."
88 template<class T, class VoidAllocator, class Deleter>
89 class shared_ptr
91 /// @cond
92 private:
93 typedef shared_ptr<T, VoidAllocator, Deleter> this_type;
94 /// @endcond
96 public:
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;
111 public:
112 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(shared_ptr)
114 //!Constructs an empty shared_ptr.
115 //!Use_count() == 0 && get()== 0.
116 shared_ptr()
117 : m_pn() // never throws
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)
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) );
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)
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
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
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); }
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)
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)
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)
181 if(!m_pn.get_pointer()){ // need to allocate new counter -- the cast failed
182 m_pn = detail::shared_count<T, VoidAllocator, Deleter>();
185 /// @endcond
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)
192 m_pn = r.m_pn; // shared_count::op= doesn't throw
193 return *this;
196 //!Move-assignment. Equivalent to shared_ptr(other).swap(*this).
197 //!Never throws
198 shared_ptr & operator=(BOOST_INTERPROCESS_RV_REF(shared_ptr) other) // never throws
200 this_type(other).swap(*this);
201 return *this;
204 //!This is equivalent to:
205 //!this_type().swap(*this);
206 void reset()
208 this_type().swap(*this);
211 //!This is equivalent to:
212 //!this_type(p, a, d).swap(*this);
213 template<class Pointer>
214 void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
216 //Check that the pointer passed is of the same type that
217 //the pointer the allocator defines or it's a raw pointer
218 typedef typename boost::pointer_to_other<Pointer, T>::type ParameterPointer;
219 BOOST_STATIC_ASSERT((detail::is_same<pointer, ParameterPointer>::value) ||
220 (detail::is_pointer<Pointer>::value));
221 this_type(p, a, d).swap(*this);
224 template<class Y>
225 void reset(shared_ptr<Y, VoidAllocator, Deleter> const & r, const pointer &p)
227 this_type(r, p).swap(*this);
230 //!Returns a reference to the
231 //!pointed type
232 reference operator* () const // never throws
233 { BOOST_ASSERT(m_pn.get_pointer() != 0); return *m_pn.get_pointer(); }
235 //!Returns the pointer pointing
236 //!to the owned object
237 pointer operator-> () const // never throws
238 { BOOST_ASSERT(m_pn.get_pointer() != 0); return m_pn.get_pointer(); }
240 //!Returns the pointer pointing
241 //!to the owned object
242 pointer get() const // never throws
243 { return m_pn.get_pointer(); }
245 /// @cond
246 // implicit conversion to "bool"
247 void unspecified_bool_type_func() const {}
248 typedef void (this_type::*unspecified_bool_type)() const;
250 operator unspecified_bool_type() const // never throws
251 { return !m_pn.get_pointer() ? 0 : &this_type::unspecified_bool_type_func; }
252 /// @endcond
254 //!Not operator.
255 //!Returns true if this->get() != 0, false otherwise
256 bool operator! () const // never throws
257 { return !m_pn.get_pointer(); }
259 //!Returns use_count() == 1.
260 //!unique() might be faster than use_count()
261 bool unique() const // never throws
262 { return m_pn.unique(); }
264 //!Returns the number of shared_ptr objects, *this included,
265 //!that share ownership with *this, or an unspecified nonnegative
266 //!value when *this is empty.
267 //!use_count() is not necessarily efficient. Use only for
268 //!debugging and testing purposes, not for production code.
269 long use_count() const // never throws
270 { return m_pn.use_count(); }
272 //!Exchanges the contents of the two
273 //!smart pointers.
274 void swap(shared_ptr<T, VoidAllocator, Deleter> & other) // never throws
275 { m_pn.swap(other.m_pn); }
277 /// @cond
279 template<class T2, class A2, class Deleter2>
280 bool _internal_less(shared_ptr<T2, A2, Deleter2> const & rhs) const
281 { return m_pn < rhs.m_pn; }
283 const_deleter_pointer get_deleter() const
284 { return m_pn.get_deleter(); }
286 // const_allocator_pointer get_allocator() const
287 // { return m_pn.get_allocator(); }
289 private:
291 template<class T2, class A2, class Deleter2> friend class shared_ptr;
292 template<class T2, class A2, class Deleter2> friend class weak_ptr;
294 detail::shared_count<T, VoidAllocator, Deleter> m_pn; // reference counter
295 /// @endcond
296 }; // shared_ptr
298 template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
299 bool operator==(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
300 { return a.get() == b.get(); }
302 template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
303 bool operator!=(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
304 { return a.get() != b.get(); }
306 template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
307 bool operator<(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
308 { return a._internal_less(b); }
310 template<class T, class VoidAllocator, class Deleter> inline
311 void swap(shared_ptr<T, VoidAllocator, Deleter> & a, shared_ptr<T, VoidAllocator, Deleter> & b)
312 { a.swap(b); }
314 template<class T, class VoidAllocator, class Deleter, class U> inline
315 shared_ptr<T, VoidAllocator, Deleter> static_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
316 { return shared_ptr<T, VoidAllocator, Deleter>(r, detail::static_cast_tag()); }
318 template<class T, class VoidAllocator, class Deleter, class U> inline
319 shared_ptr<T, VoidAllocator, Deleter> const_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
320 { return shared_ptr<T, VoidAllocator, Deleter>(r, detail::const_cast_tag()); }
322 template<class T, class VoidAllocator, class Deleter, class U> inline
323 shared_ptr<T, VoidAllocator, Deleter> dynamic_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
324 { return shared_ptr<T, VoidAllocator, Deleter>(r, detail::dynamic_cast_tag()); }
326 // get_pointer() enables boost::mem_fn to recognize shared_ptr
327 template<class T, class VoidAllocator, class Deleter> inline
328 T * get_pointer(shared_ptr<T, VoidAllocator, Deleter> const & p)
329 { return p.get(); }
331 // operator<<
332 template<class E, class T, class Y, class VoidAllocator, class Deleter> inline
333 std::basic_ostream<E, T> & operator<<
334 (std::basic_ostream<E, T> & os, shared_ptr<Y, VoidAllocator, Deleter> const & p)
335 { os << p.get(); return os; }
337 //!Returns the type of a shared pointer
338 //!of type T with the allocator boost::interprocess::allocator allocator
339 //!and boost::interprocess::deleter deleter
340 //!that can be constructed in the given managed segment type.
341 template<class T, class ManagedMemory>
342 struct managed_shared_ptr
344 typedef typename ManagedMemory::template allocator<void>::type void_allocator;
345 typedef typename ManagedMemory::template deleter<T>::type deleter;
346 typedef shared_ptr< T, void_allocator, deleter> type;
349 //!Returns an instance of a shared pointer constructed
350 //!with the default allocator and deleter from a pointer
351 //!of type T that has been allocated in the passed managed segment
352 template<class T, class ManagedMemory>
353 inline typename managed_shared_ptr<T, ManagedMemory>::type
354 make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory)
356 return typename managed_shared_ptr<T, ManagedMemory>::type
357 ( constructed_object
358 , managed_memory.template get_allocator<void>()
359 , managed_memory.template get_deleter<T>()
363 } // namespace interprocess
365 /// @cond
367 #if defined(_MSC_VER) && (_MSC_VER < 1400)
368 // get_pointer() enables boost::mem_fn to recognize shared_ptr
369 template<class T, class VoidAllocator, class Deleter> inline
370 T * get_pointer(boost::interprocess::shared_ptr<T, VoidAllocator, Deleter> const & p)
371 { return p.get(); }
372 #endif
374 /// @endcond
376 } // namespace boost
378 #include <boost/interprocess/detail/config_end.hpp>
380 #endif // #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED