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-2012. 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/move/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 ipcdetail {
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
struct nat2 {int for_nullptr;};
87
typedef int nat2::*nullptr_t;
88
typedef typename ipcdetail::add_reference<D>::type deleter_reference;
89
typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference;
94
typedef T element_type;
95
typedef D deleter_type;
96
typedef typename ipcdetail::pointer_type<T, D>::type pointer;
98
//!Requires: D must be default constructible, and that construction must not
99
//!throw an exception. D must not be a reference type.
101
//!Effects: Constructs a unique_ptr which owns nothing.
103
//!Postconditions: get() == 0. get_deleter() returns a reference to a
104
//!default constructed deleter D.
111
//!Requires: The expression D()(p) must be well formed. The default constructor
112
//!of D must not throw an exception.
114
//!D must not be a reference type.
116
//!Effects: Constructs a unique_ptr which owns p.
118
//!Postconditions: get() == p. get_deleter() returns a reference to a default constructed deleter D.
121
explicit unique_ptr(pointer p)
125
//!Requires: The expression d(p) must be well formed.
127
//!Postconditions: get() == p. get_deleter() returns a reference to the
128
//!internally stored deleter. If D is a
129
//!reference type then get_deleter() returns a reference to the lvalue d.
133
,typename ipcdetail::if_<ipcdetail::is_reference<D>
135
,typename ipcdetail::add_reference<const D>::type>::type d)
139
//!Requires: If the deleter is not a reference type, construction of the
140
//!deleter D from an lvalue D must not throw an exception.
142
//!Effects: Constructs a unique_ptr which owns the pointer which u owns
143
//!(if any). If the deleter is not a reference type, it is move constructed
144
//!from u's deleter, otherwise the reference is copy constructed from u's deleter.
146
//!After the construction, u no longer owns a pointer.
147
//![ Note: The deleter constructor can be implemented with
148
//! boost::forward<D>. -end note ]
150
//!Postconditions: get() == value u.get() had before the construction.
151
//!get_deleter() returns a reference to the internally stored deleter which
152
//!was constructed from u.get_deleter(). If D is a reference type then get_-
153
//!deleter() and u.get_deleter() both reference the same lvalue deleter.
156
unique_ptr(BOOST_RV_REF(unique_ptr) u)
157
: ptr_(u.release(), boost::forward<D>(u.get_deleter()))
160
//!Requires: If D is not a reference type, construction of the deleter
161
//!D from an rvalue of type E must be well formed
162
//!and not throw an exception. If D is a reference type, then E must be
163
//!the same type as D (diagnostic required). unique_ptr<U, E>::pointer
164
//!must be implicitly convertible to pointer.
166
//!Effects: Constructs a unique_ptr which owns the pointer which u owns
167
//!(if any). If the deleter is not a reference
168
//!type, it is move constructed from u's deleter, otherwise the reference
169
//!is copy constructed from u's deleter.
171
//!After the construction, u no longer owns a pointer.
173
//!postconditions get() == value u.get() had before the construction,
174
//!modulo any required offset adjustments
175
//!resulting from the cast from U* to T*. get_deleter() returns a reference to the internally stored deleter which
176
//!was constructed from u.get_deleter().
179
template <class U, class E>
180
unique_ptr(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u,
181
typename ipcdetail::enable_if_c<
182
ipcdetail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
183
ipcdetail::is_convertible<E, D>::value &&
185
!ipcdetail::is_reference<D>::value ||
186
ipcdetail::is_same<D, E>::value
191
: ptr_(const_cast<unique_ptr<U,E>&>(u).release(), boost::move<D>(u.get_deleter()))
194
//!Effects: If get() == 0 there are no effects. Otherwise get_deleter()(get()).
202
//!Requires: Assignment of the deleter D from an rvalue D must not throw an exception.
204
//!Effects: reset(u.release()) followed by a move assignment from u's deleter to
207
//!Postconditions: This unique_ptr now owns the pointer which u owned, and u no
213
unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u)
216
ptr_.second() = boost::move(u.get_deleter());
220
//!Requires: Assignment of the deleter D from an rvalue D must not
221
//!throw an exception. U* must be implicitly convertible to T*.
223
//!Effects: reset(u.release()) followed by a move assignment from
224
//!u's deleter to this deleter. If either D or E is
225
//!a reference type, then the referenced lvalue deleter participates
226
//!in the move assignment.
228
//!Postconditions: This unique_ptr now owns the pointer which u owned,
229
//!and u no longer owns it.
234
template <class U, class E>
235
unique_ptr& operator=(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u)
238
ptr_.second() = boost::move(u.get_deleter());
242
//!Assigns from the literal 0 or NULL.
246
//!Postcondition: get() == 0
251
unique_ptr& operator=(nullptr_t)
257
//!Requires: get() != 0.
260
typename ipcdetail::add_reference<T>::type operator*() const
261
{ return *ptr_.first(); }
263
//!Requires: get() != 0.
266
pointer operator->() const
267
{ return ptr_.first(); }
269
//!Returns: The stored pointer.
272
{ return ptr_.first(); }
274
//!Returns: A reference to the stored deleter.
277
deleter_reference get_deleter()
278
{ return ptr_.second(); }
280
//!Returns: A const reference to the stored deleter.
283
deleter_const_reference get_deleter() const
284
{ return ptr_.second(); }
286
//!Returns: An unspecified value that, when used in boolean
287
//!contexts, is equivalent to get() != 0.
290
operator int nat::*() const
291
{ return ptr_.first() ? &nat::for_bool : 0; }
293
//!Postcondition: get() == 0.
295
//!Returns: The value get() had at the start of the call to release.
300
pointer tmp = ptr_.first();
305
//!Effects: If p == get() there are no effects. Otherwise get_deleter()(get()).
307
//!Postconditions: get() == p.
310
void reset(pointer p = 0)
312
if (ptr_.first() != p){
314
ptr_.second()(ptr_.first());
319
//!Requires: The deleter D is Swappable and will not throw an exception under swap.
321
//!Effects: The stored pointers of this and u are exchanged.
322
//! The stored deleters are swapped (unqualified).
324
void swap(unique_ptr& u)
325
{ ptr_.swap(u.ptr_); }
329
boost::compressed_pair<pointer, D> ptr_;
330
BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr)
331
template <class U, class E> unique_ptr(unique_ptr<U, E>&);
332
template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0);
334
template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&);
335
template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&);
339
template <class T, class D>
340
class unique_ptr<T[], D>
342
struct nat {int for_bool_;};
343
typedef typename ipcdetail::add_reference<D>::type deleter_reference;
344
typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference;
346
typedef T element_type;
347
typedef D deleter_type;
348
typedef typename ipcdetail::pointer_type<T, D>::type pointer;
351
unique_ptr() : ptr_(pointer()) {}
352
explicit unique_ptr(pointer p) : ptr_(p) {}
353
unique_ptr(pointer p, typename if_<
354
boost::is_reference<D>,
356
typename ipcdetail::add_reference<const D>::type>::type d)
358
unique_ptr(const unique_ptr& u)
359
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
362
~unique_ptr() {reset();}
365
unique_ptr& operator=(const unique_ptr& cu)
367
unique_ptr& u = const_cast<unique_ptr&>(cu);
369
ptr_.second() = u.get_deleter();
372
unique_ptr& operator=(int nat::*)
379
typename ipcdetail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
380
pointer get() const {return ptr_.first();}
381
deleter_reference get_deleter() {return ptr_.second();}
382
deleter_const_reference get_deleter() const {return ptr_.second();}
383
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
388
pointer tmp = ptr_.first();
392
void reset(pointer p = 0)
394
if (ptr_.first() != p)
397
ptr_.second()(ptr_.first());
401
void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
403
boost::compressed_pair<pointer, D> ptr_;
405
template <class U, class E> unique_ptr(U p, E,
406
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
407
template <class U> explicit unique_ptr(U,
408
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
410
unique_ptr(unique_ptr&);
411
template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0);
413
unique_ptr& operator=(unique_ptr&);
414
template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&);
417
template <class T, class D, std::size_t N>
418
class unique_ptr<T[N], D>
420
struct nat {int for_bool_;};
421
typedef typename ipcdetail::add_reference<D>::type deleter_reference;
422
typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference;
424
typedef T element_type;
425
typedef D deleter_type;
426
typedef typename ipcdetail::pointer_type<T, D>::type pointer;
427
static const std::size_t size = N;
430
unique_ptr() : ptr_(0) {}
431
explicit unique_ptr(pointer p) : ptr_(p) {}
432
unique_ptr(pointer p, typename if_<
433
boost::is_reference<D>,
435
typename ipcdetail::add_reference<const D>::type>::type d)
437
unique_ptr(const unique_ptr& u)
438
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
441
~unique_ptr() {reset();}
444
unique_ptr& operator=(const unique_ptr& cu)
446
unique_ptr& u = const_cast<unique_ptr&>(cu);
448
ptr_.second() = u.get_deleter();
451
unique_ptr& operator=(int nat::*)
458
typename ipcdetail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
459
pointer get() const {return ptr_.first();}
460
deleter_reference get_deleter() {return ptr_.second();}
461
deleter_const_reference get_deleter() const {return ptr_.second();}
462
operator int nat::*() const {return ptr_.first() ? &nat::for_bool : 0;}
467
pointer tmp = ptr_.first();
471
void reset(pointer p = 0)
473
if (ptr_.first() != p)
476
ptr_.second()(ptr_.first(), N);
480
void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
482
boost::compressed_pair<pointer, D> ptr_;
484
template <class U, class E> unique_ptr(U p, E,
485
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
486
template <class U> explicit unique_ptr(U,
487
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
489
unique_ptr(unique_ptr&);
490
template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0);
492
unique_ptr& operator=(unique_ptr&);
493
template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&);
496
template <class T, class D> inline
497
void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y)
500
template <class T1, class D1, class T2, class D2> inline
501
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
502
{ return x.get() == y.get(); }
504
template <class T1, class D1, class T2, class D2> inline
505
bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
506
{ return x.get() != y.get(); }
508
template <class T1, class D1, class T2, class D2> inline
509
bool operator <(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
510
{ return x.get() < y.get(); }
512
template <class T1, class D1, class T2, class D2> inline
513
bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
514
{ return x.get() <= y.get(); }
516
template <class T1, class D1, class T2, class D2> inline
517
bool operator >(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
518
{ return x.get() > y.get(); }
520
template <class T1, class D1, class T2, class D2> inline
521
bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
522
{ return x.get() >= y.get(); }
525
//!Returns the type of a unique pointer
526
//!of type T with boost::interprocess::deleter deleter
527
//!that can be constructed in the given managed segment type.
528
template<class T, class ManagedMemory>
529
struct managed_unique_ptr
533
, typename ManagedMemory::template deleter<T>::type
537
//!Returns an instance of a unique pointer constructed
538
//!with boost::interproces::deleter from a pointer
539
//!of type T that has been allocated in the passed managed segment
540
template<class T, class ManagedMemory>
541
inline typename managed_unique_ptr<T, ManagedMemory>::type
542
make_managed_unique_ptr(T *constructed_object, ManagedMemory &managed_memory)
544
return typename managed_unique_ptr<T, ManagedMemory>::type
545
(constructed_object, managed_memory.template get_deleter<T>());
548
} //namespace interprocess{
551
#include <boost/interprocess/detail/config_end.hpp>
553
#endif //#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED