1 //////////////////////////////////////////////////////////////////////////////
2 // I, Howard Hinnant, hereby place this code in the public domain.
3 //////////////////////////////////////////////////////////////////////////////
5 // This file is the adaptation for Interprocess of
6 // Howard Hinnant's unique_ptr emulation code.
8 // (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
9 // Software License, Version 1.0. (See accompanying file
10 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12 // See http://www.boost.org/libs/interprocess for documentation.
14 //////////////////////////////////////////////////////////////////////////////
16 #ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED
17 #define BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED
19 #include <boost/interprocess/detail/config_begin.hpp>
20 #include <boost/interprocess/detail/workaround.hpp>
21 #include <boost/assert.hpp>
22 #include <boost/interprocess/detail/utilities.hpp>
23 #include <boost/interprocess/detail/pointer_type.hpp>
24 #include <boost/interprocess/detail/move.hpp>
25 #include <boost/compressed_pair.hpp>
26 #include <boost/static_assert.hpp>
27 #include <boost/interprocess/detail/mpl.hpp>
28 #include <boost/interprocess/detail/type_traits.hpp>
29 #include <boost/interprocess/smart_ptr/deleter.hpp>
33 //!Describes the smart pointer unique_ptr
36 namespace interprocess
{
39 template <class T
, class D
> class unique_ptr
;
43 template <class T
> struct unique_ptr_error
;
45 template <class T
, class D
>
46 struct unique_ptr_error
<const unique_ptr
<T
, D
> >
48 typedef unique_ptr
<T
, D
> type
;
51 } //namespace detail {
54 //!Template unique_ptr stores a pointer to an object and deletes that object
55 //!using the associated deleter when it is itself destroyed (such as when
56 //!leaving block scope.
58 //!The unique_ptr provides a semantics of strict ownership. A unique_ptr owns the
59 //!object it holds a pointer to.
61 //!A unique_ptr is not CopyConstructible, nor CopyAssignable, however it is
62 //!MoveConstructible and Move-Assignable.
64 //!The uses of unique_ptr include providing exception safety for dynamically
65 //!allocated memory, passing ownership of dynamically allocated memory to a
66 //!function, and returning dynamically allocated memory from a function
68 //!A client-supplied template argument D must be a
69 //!function pointer or functor for which, given a value d of type D and a pointer
70 //!ptr to a type T*, the expression d(ptr) is
71 //!valid and has the effect of deallocating the pointer as appropriate for that
72 //!deleter. D may also be an lvalue-reference to a deleter.
74 //!If the deleter D maintains state, it is intended that this state stay with
75 //!the associated pointer as ownership is transferred
76 //!from unique_ptr to unique_ptr. The deleter state need never be copied,
77 //!only moved or swapped as pointer ownership
78 //!is moved around. That is, the deleter need only be MoveConstructible,
79 //!MoveAssignable, and Swappable, and need not be CopyConstructible
80 //!(unless copied into the unique_ptr) nor CopyAssignable.
81 template <class T
, class D
>
85 struct nat
{int for_bool_
;};
86 typedef typename
detail::add_reference
<D
>::type deleter_reference
;
87 typedef typename
detail::add_reference
<const D
>::type deleter_const_reference
;
91 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(unique_ptr
)
93 typedef T element_type
;
94 typedef D deleter_type
;
95 typedef typename
detail::pointer_type
<T
, D
>::type pointer
;
97 //!Requires: D must be default constructible, and that construction must not
98 //!throw an exception. D must not be a reference type.
100 //!Effects: Constructs a unique_ptr which owns nothing.
102 //!Postconditions: get() == 0. get_deleter() returns a reference to a
103 //!default constructed deleter D.
110 //!Requires: The expression D()(p) must be well formed. The default constructor
111 //!of D must not throw an exception.
113 //!D must not be a reference type.
115 //!Effects: Constructs a unique_ptr which owns p.
117 //!Postconditions: get() == p. get_deleter() returns a reference to a default constructed deleter D.
120 explicit unique_ptr(pointer p
)
124 //!Requires: The expression d(p) must be well formed.
126 //!Postconditions: get() == p. get_deleter() returns a reference to the
127 //!internally stored deleter. If D is a
128 //!reference type then get_deleter() returns a reference to the lvalue d.
132 ,typename
detail::if_
<detail::is_reference
<D
>
134 ,typename
detail::add_reference
<const D
>::type
>::type d
)
138 //!Requires: If the deleter is not a reference type, construction of the
139 //!deleter D from an lvalue D must not throw an exception.
141 //!Effects: Constructs a unique_ptr which owns the pointer which u owns
142 //!(if any). If the deleter is not a reference type, it is move constructed
143 //!from u's deleter, otherwise the reference is copy constructed from u's deleter.
145 //!After the construction, u no longer owns a pointer.
146 //![ Note: The deleter constructor can be implemented with
147 //! boost::interprocess::forward<D>. -end note ]
149 //!Postconditions: get() == value u.get() had before the construction.
150 //!get_deleter() returns a reference to the internally stored deleter which
151 //!was constructed from u.get_deleter(). If D is a reference type then get_-
152 //!deleter() and u.get_deleter() both reference the same lvalue deleter.
155 unique_ptr(BOOST_INTERPROCESS_RV_REF(unique_ptr
) u
)
156 : ptr_(u
.release(), boost::interprocess::forward
<D
>(u
.get_deleter()))
159 //!Requires: If D is not a reference type, construction of the deleter
160 //!D from an rvalue of type E must be well formed
161 //!and not throw an exception. If D is a reference type, then E must be
162 //!the same type as D (diagnostic required). unique_ptr<U, E>::pointer
163 //!must be implicitly convertible to pointer.
165 //!Effects: Constructs a unique_ptr which owns the pointer which u owns
166 //!(if any). If the deleter is not a reference
167 //!type, it is move constructed from u's deleter, otherwise the reference
168 //!is copy constructed from u's deleter.
170 //!After the construction, u no longer owns a pointer.
172 //!postconditions get() == value u.get() had before the construction,
173 //!modulo any required offset adjustments
174 //!resulting from the cast from U* to T*. get_deleter() returns a reference to the internally stored deleter which
175 //!was constructed from u.get_deleter().
178 template <class U
, class E
>
179 unique_ptr(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(unique_ptr
, U
, E
) u
,
180 typename
detail::enable_if_c
<
181 detail::is_convertible
<typename unique_ptr
<U
, E
>::pointer
, pointer
>::value
&&
182 detail::is_convertible
<E
, D
>::value
&&
184 !detail::is_reference
<D
>::value
||
185 detail::is_same
<D
, E
>::value
190 : ptr_(const_cast<unique_ptr
<U
,E
>&>(u
).release(), boost::interprocess::move
<D
>(u
.get_deleter()))
193 //!Effects: If get() == 0 there are no effects. Otherwise get_deleter()(get()).
201 //!Requires: Assignment of the deleter D from an rvalue D must not throw an exception.
203 //!Effects: reset(u.release()) followed by a move assignment from u's deleter to
206 //!Postconditions: This unique_ptr now owns the pointer which u owned, and u no
212 unique_ptr
& operator=(BOOST_INTERPROCESS_RV_REF(unique_ptr
) u
)
215 ptr_
.second() = boost::interprocess::move(u
.get_deleter());
219 //!Requires: Assignment of the deleter D from an rvalue D must not
220 //!throw an exception. U* must be implicitly convertible to T*.
222 //!Effects: reset(u.release()) followed by a move assignment from
223 //!u's deleter to this deleter. If either D or E is
224 //!a reference type, then the referenced lvalue deleter participates
225 //!in the move assignment.
227 //!Postconditions: This unique_ptr now owns the pointer which u owned,
228 //!and u no longer owns it.
233 template <class U
, class E
>
234 unique_ptr
& operator=(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(unique_ptr
, U
, E
) u
)
237 ptr_
.second() = boost::interprocess::move(u
.get_deleter());
241 //!Assigns from the literal 0 or NULL.
245 //!Postcondition: get() == 0
250 unique_ptr
& operator=(int nat::*)
256 //!Requires: get() != 0.
259 typename
detail::add_reference
<T
>::type
operator*() const
260 { return *ptr_
.first(); }
262 //!Requires: get() != 0.
265 pointer
operator->() const
266 { return ptr_
.first(); }
268 //!Returns: The stored pointer.
271 { return ptr_
.first(); }
273 //!Returns: A reference to the stored deleter.
276 deleter_reference
get_deleter()
277 { return ptr_
.second(); }
279 //!Returns: A const reference to the stored deleter.
282 deleter_const_reference
get_deleter() const
283 { return ptr_
.second(); }
285 //!Returns: An unspecified value that, when used in boolean
286 //!contexts, is equivalent to get() != 0.
289 operator int nat::*() const
290 { return ptr_
.first() ? &nat::for_bool_
: 0; }
292 //!Postcondition: get() == 0.
294 //!Returns: The value get() had at the start of the call to release.
299 pointer tmp
= ptr_
.first();
304 //!Effects: If p == get() there are no effects. Otherwise get_deleter()(get()).
306 //!Postconditions: get() == p.
309 void reset(pointer p
= 0)
311 if (ptr_
.first() != p
){
313 ptr_
.second()(ptr_
.first());
318 //!Requires: The deleter D is Swappable and will not throw an exception under swap.
320 //!Effects: The stored pointers of this and u are exchanged.
321 //! The stored deleters are swapped (unqualified).
323 void swap(unique_ptr
& u
)
324 { ptr_
.swap(u
.ptr_
); }
328 boost::compressed_pair
<pointer
, D
> ptr_
;
330 unique_ptr(unique_ptr
&);
331 template <class U
, class E
> unique_ptr(unique_ptr
<U
, E
>&);
332 template <class U
> unique_ptr(U
&, typename
detail::unique_ptr_error
<U
>::type
= 0);
334 unique_ptr
& operator=(unique_ptr
&);
335 template <class U
, class E
> unique_ptr
& operator=(unique_ptr
<U
, E
>&);
336 template <class U
> typename
detail::unique_ptr_error
<U
>::type
operator=(U
&);
340 template <class T, class D>
341 class unique_ptr<T[], D>
343 struct nat {int for_bool_;};
344 typedef typename detail::add_reference<D>::type deleter_reference;
345 typedef typename detail::add_reference<const D>::type deleter_const_reference;
347 typedef T element_type;
348 typedef D deleter_type;
349 typedef typename detail::pointer_type<T, D>::type pointer;
352 unique_ptr() : ptr_(pointer()) {}
353 explicit unique_ptr(pointer p) : ptr_(p) {}
354 unique_ptr(pointer p, typename if_<
355 boost::is_reference<D>,
357 typename detail::add_reference<const D>::type>::type d)
359 unique_ptr(const unique_ptr& u)
360 : ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
363 ~unique_ptr() {reset();}
366 unique_ptr& operator=(const unique_ptr& cu)
368 unique_ptr& u = const_cast<unique_ptr&>(cu);
370 ptr_.second() = u.get_deleter();
373 unique_ptr& operator=(int nat::*)
380 typename detail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
381 pointer get() const {return ptr_.first();}
382 deleter_reference get_deleter() {return ptr_.second();}
383 deleter_const_reference get_deleter() const {return ptr_.second();}
384 operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
389 pointer tmp = ptr_.first();
393 void reset(pointer p = 0)
395 if (ptr_.first() != p)
398 ptr_.second()(ptr_.first());
402 void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
404 boost::compressed_pair<pointer, D> ptr_;
406 template <class U, class E> unique_ptr(U p, E,
407 typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
408 template <class U> explicit unique_ptr(U,
409 typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
411 unique_ptr(unique_ptr&);
412 template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
414 unique_ptr& operator=(unique_ptr&);
415 template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
418 template <class T, class D, std::size_t N>
419 class unique_ptr<T[N], D>
421 struct nat {int for_bool_;};
422 typedef typename detail::add_reference<D>::type deleter_reference;
423 typedef typename detail::add_reference<const D>::type deleter_const_reference;
425 typedef T element_type;
426 typedef D deleter_type;
427 typedef typename detail::pointer_type<T, D>::type pointer;
428 static const std::size_t size = N;
431 unique_ptr() : ptr_(0) {}
432 explicit unique_ptr(pointer p) : ptr_(p) {}
433 unique_ptr(pointer p, typename if_<
434 boost::is_reference<D>,
436 typename detail::add_reference<const D>::type>::type d)
438 unique_ptr(const unique_ptr& u)
439 : ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
442 ~unique_ptr() {reset();}
445 unique_ptr& operator=(const unique_ptr& cu)
447 unique_ptr& u = const_cast<unique_ptr&>(cu);
449 ptr_.second() = u.get_deleter();
452 unique_ptr& operator=(int nat::*)
459 typename detail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
460 pointer get() const {return ptr_.first();}
461 deleter_reference get_deleter() {return ptr_.second();}
462 deleter_const_reference get_deleter() const {return ptr_.second();}
463 operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
468 pointer tmp = ptr_.first();
472 void reset(pointer p = 0)
474 if (ptr_.first() != p)
477 ptr_.second()(ptr_.first(), N);
481 void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
483 boost::compressed_pair<pointer, D> ptr_;
485 template <class U, class E> unique_ptr(U p, E,
486 typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
487 template <class U> explicit unique_ptr(U,
488 typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
490 unique_ptr(unique_ptr&);
491 template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
493 unique_ptr& operator=(unique_ptr&);
494 template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
497 template <class T
, class D
> inline
498 void swap(unique_ptr
<T
, D
>& x
, unique_ptr
<T
, D
>& y
)
501 template <class T1
, class D1
, class T2
, class D2
> inline
502 bool operator==(const unique_ptr
<T1
, D1
>& x
, const unique_ptr
<T2
, D2
>& y
)
503 { return x
.get() == y
.get(); }
505 template <class T1
, class D1
, class T2
, class D2
> inline
506 bool operator!=(const unique_ptr
<T1
, D1
>& x
, const unique_ptr
<T2
, D2
>& y
)
507 { return x
.get() != y
.get(); }
509 template <class T1
, class D1
, class T2
, class D2
> inline
510 bool operator <(const unique_ptr
<T1
, D1
>& x
, const unique_ptr
<T2
, D2
>& y
)
511 { return x
.get() < y
.get(); }
513 template <class T1
, class D1
, class T2
, class D2
> inline
514 bool operator<=(const unique_ptr
<T1
, D1
>& x
, const unique_ptr
<T2
, D2
>& y
)
515 { return x
.get() <= y
.get(); }
517 template <class T1
, class D1
, class T2
, class D2
> inline
518 bool operator >(const unique_ptr
<T1
, D1
>& x
, const unique_ptr
<T2
, D2
>& y
)
519 { return x
.get() > y
.get(); }
521 template <class T1
, class D1
, class T2
, class D2
> inline
522 bool operator>=(const unique_ptr
<T1
, D1
>& x
, const unique_ptr
<T2
, D2
>& y
)
523 { return x
.get() >= y
.get(); }
526 //!Returns the type of a unique pointer
527 //!of type T with boost::interprocess::deleter deleter
528 //!that can be constructed in the given managed segment type.
529 template<class T
, class ManagedMemory
>
530 struct managed_unique_ptr
534 , typename
ManagedMemory::template deleter
<T
>::type
538 //!Returns an instance of a unique pointer constructed
539 //!with boost::interproces::deleter from a pointer
540 //!of type T that has been allocated in the passed managed segment
541 template<class T
, class ManagedMemory
>
542 inline typename managed_unique_ptr
<T
, ManagedMemory
>::type
543 make_managed_unique_ptr(T
*constructed_object
, ManagedMemory
&managed_memory
)
545 return typename managed_unique_ptr
<T
, ManagedMemory
>::type
546 (constructed_object
, managed_memory
.template get_deleter
<T
>());
549 } //namespace interprocess{
552 #include <boost/interprocess/detail/config_end.hpp>
554 #endif //#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED