1 //////////////////////////////////////////////////////////////////////////////
3 // This file is the adaptation for Interprocess of boost/shared_ptr.hpp
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
40 //!Describes the smart pointer shared_ptr
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
;
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
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 &, ...)
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.
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.
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>).
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
>
93 typedef shared_ptr
<T
, VoidAllocator
, Deleter
> this_type
;
98 typedef T element_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
;
112 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(shared_ptr
)
114 //!Constructs an empty shared_ptr.
115 //!Use_count() == 0 && get()== 0.
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())
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().
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.
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.
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.
159 explicit shared_ptr(BOOST_INTERPROCESS_RV_REF(shared_ptr
) other
)
161 { this->swap(other
); }
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())))
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())))
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())))
181 if(!m_pn
.get_pointer()){ // need to allocate new counter -- the cast failed
182 m_pn
= detail::shared_count
<T
, VoidAllocator
, Deleter
>();
187 //!Equivalent to shared_ptr(r).swap(*this).
190 shared_ptr
& operator=(shared_ptr
<Y
, VoidAllocator
, Deleter
> const & r
)
192 m_pn
= r
.m_pn
; // shared_count::op= doesn't throw
196 //!Move-assignment. Equivalent to shared_ptr(other).swap(*this).
198 shared_ptr
& operator=(BOOST_INTERPROCESS_RV_REF(shared_ptr
) other
) // never throws
200 this_type(other
).swap(*this);
204 //!This is equivalent to:
205 //!this_type().swap(*this);
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);
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
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(); }
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
; }
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
274 void swap(shared_ptr
<T
, VoidAllocator
, Deleter
> & other
) // never throws
275 { m_pn
.swap(other
.m_pn
); }
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(); }
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
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
)
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
)
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
358 , managed_memory
.template get_allocator
<void>()
359 , managed_memory
.template get_deleter
<T
>()
363 } // namespace interprocess
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
)
378 #include <boost/interprocess/detail/config_end.hpp>
380 #endif // #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED