You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
551 lines
18 KiB
551 lines
18 KiB
////////////////////////////////////////////////////////////////////////////// |
|
// I, Howard Hinnant, hereby place this code in the public domain. |
|
////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// This file is the adaptation for Interprocess of |
|
// Howard Hinnant's unique_ptr emulation code. |
|
// |
|
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost |
|
// Software License, Version 1.0. (See accompanying file |
|
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
|
// |
|
// See http://www.boost.org/libs/interprocess for documentation. |
|
// |
|
////////////////////////////////////////////////////////////////////////////// |
|
|
|
#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED |
|
#define BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED |
|
|
|
#include <boost/interprocess/detail/config_begin.hpp> |
|
#include <boost/interprocess/detail/workaround.hpp> |
|
#include <boost/assert.hpp> |
|
#include <boost/interprocess/detail/utilities.hpp> |
|
#include <boost/interprocess/detail/pointer_type.hpp> |
|
#include <boost/interprocess/detail/move.hpp> |
|
#include <boost/compressed_pair.hpp> |
|
#include <boost/static_assert.hpp> |
|
#include <boost/interprocess/detail/mpl.hpp> |
|
#include <boost/interprocess/detail/type_traits.hpp> |
|
#include <boost/interprocess/smart_ptr/deleter.hpp> |
|
#include <cstddef> |
|
|
|
//!\file |
|
//!Describes the smart pointer unique_ptr |
|
|
|
namespace boost{ |
|
namespace interprocess{ |
|
|
|
/// @cond |
|
template <class T, class D> class unique_ptr; |
|
|
|
namespace ipcdetail { |
|
|
|
template <class T> struct unique_ptr_error; |
|
|
|
template <class T, class D> |
|
struct unique_ptr_error<const unique_ptr<T, D> > |
|
{ |
|
typedef unique_ptr<T, D> type; |
|
}; |
|
|
|
} //namespace ipcdetail { |
|
/// @endcond |
|
|
|
//!Template unique_ptr stores a pointer to an object and deletes that object |
|
//!using the associated deleter when it is itself destroyed (such as when |
|
//!leaving block scope. |
|
//! |
|
//!The unique_ptr provides a semantics of strict ownership. A unique_ptr owns the |
|
//!object it holds a pointer to. |
|
//! |
|
//!A unique_ptr is not CopyConstructible, nor CopyAssignable, however it is |
|
//!MoveConstructible and Move-Assignable. |
|
//! |
|
//!The uses of unique_ptr include providing exception safety for dynamically |
|
//!allocated memory, passing ownership of dynamically allocated memory to a |
|
//!function, and returning dynamically allocated memory from a function |
|
//! |
|
//!A client-supplied template argument D must be a |
|
//!function pointer or functor for which, given a value d of type D and a pointer |
|
//!ptr to a type T*, the expression d(ptr) is |
|
//!valid and has the effect of deallocating the pointer as appropriate for that |
|
//!deleter. D may also be an lvalue-reference to a deleter. |
|
//! |
|
//!If the deleter D maintains state, it is intended that this state stay with |
|
//!the associated pointer as ownership is transferred |
|
//!from unique_ptr to unique_ptr. The deleter state need never be copied, |
|
//!only moved or swapped as pointer ownership |
|
//!is moved around. That is, the deleter need only be MoveConstructible, |
|
//!MoveAssignable, and Swappable, and need not be CopyConstructible |
|
//!(unless copied into the unique_ptr) nor CopyAssignable. |
|
template <class T, class D> |
|
class unique_ptr |
|
{ |
|
/// @cond |
|
struct nat {int for_bool_;}; |
|
typedef typename ipcdetail::add_reference<D>::type deleter_reference; |
|
typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference; |
|
/// @endcond |
|
|
|
public: |
|
|
|
typedef T element_type; |
|
typedef D deleter_type; |
|
typedef typename ipcdetail::pointer_type<T, D>::type pointer; |
|
|
|
//!Requires: D must be default constructible, and that construction must not |
|
//!throw an exception. D must not be a reference type. |
|
//! |
|
//!Effects: Constructs a unique_ptr which owns nothing. |
|
//! |
|
//!Postconditions: get() == 0. get_deleter() returns a reference to a |
|
//!default constructed deleter D. |
|
//! |
|
//!Throws: nothing. |
|
unique_ptr() |
|
: ptr_(pointer(0)) |
|
{} |
|
|
|
//!Requires: The expression D()(p) must be well formed. The default constructor |
|
//!of D must not throw an exception. |
|
//! |
|
//!D must not be a reference type. |
|
//! |
|
//!Effects: Constructs a unique_ptr which owns p. |
|
//! |
|
//!Postconditions: get() == p. get_deleter() returns a reference to a default constructed deleter D. |
|
//! |
|
//!Throws: nothing. |
|
explicit unique_ptr(pointer p) |
|
: ptr_(p) |
|
{} |
|
|
|
//!Requires: The expression d(p) must be well formed. |
|
//! |
|
//!Postconditions: get() == p. get_deleter() returns a reference to the |
|
//!internally stored deleter. If D is a |
|
//!reference type then get_deleter() returns a reference to the lvalue d. |
|
//! |
|
//!Throws: nothing. |
|
unique_ptr(pointer p |
|
,typename ipcdetail::if_<ipcdetail::is_reference<D> |
|
,D |
|
,typename ipcdetail::add_reference<const D>::type>::type d) |
|
: ptr_(p, d) |
|
{} |
|
|
|
//!Requires: If the deleter is not a reference type, construction of the |
|
//!deleter D from an lvalue D must not throw an exception. |
|
//! |
|
//!Effects: Constructs a unique_ptr which owns the pointer which u owns |
|
//!(if any). If the deleter is not a reference type, it is move constructed |
|
//!from u's deleter, otherwise the reference is copy constructed from u's deleter. |
|
//! |
|
//!After the construction, u no longer owns a pointer. |
|
//![ Note: The deleter constructor can be implemented with |
|
//! boost::interprocess::forward<D>. -end note ] |
|
//! |
|
//!Postconditions: get() == value u.get() had before the construction. |
|
//!get_deleter() returns a reference to the internally stored deleter which |
|
//!was constructed from u.get_deleter(). If D is a reference type then get_- |
|
//!deleter() and u.get_deleter() both reference the same lvalue deleter. |
|
//! |
|
//!Throws: nothing. |
|
unique_ptr(BOOST_RV_REF(unique_ptr) u) |
|
: ptr_(u.release(), boost::interprocess::forward<D>(u.get_deleter())) |
|
{} |
|
|
|
//!Requires: If D is not a reference type, construction of the deleter |
|
//!D from an rvalue of type E must be well formed |
|
//!and not throw an exception. If D is a reference type, then E must be |
|
//!the same type as D (diagnostic required). unique_ptr<U, E>::pointer |
|
//!must be implicitly convertible to pointer. |
|
//! |
|
//!Effects: Constructs a unique_ptr which owns the pointer which u owns |
|
//!(if any). If the deleter is not a reference |
|
//!type, it is move constructed from u's deleter, otherwise the reference |
|
//!is copy constructed from u's deleter. |
|
//! |
|
//!After the construction, u no longer owns a pointer. |
|
//! |
|
//!postconditions get() == value u.get() had before the construction, |
|
//!modulo any required offset adjustments |
|
//!resulting from the cast from U* to T*. get_deleter() returns a reference to the internally stored deleter which |
|
//!was constructed from u.get_deleter(). |
|
//! |
|
//!Throws: nothing. |
|
template <class U, class E> |
|
unique_ptr(BOOST_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u, |
|
typename ipcdetail::enable_if_c< |
|
ipcdetail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value && |
|
ipcdetail::is_convertible<E, D>::value && |
|
( |
|
!ipcdetail::is_reference<D>::value || |
|
ipcdetail::is_same<D, E>::value |
|
) |
|
, |
|
nat |
|
>::type = nat()) |
|
: ptr_(const_cast<unique_ptr<U,E>&>(u).release(), boost::interprocess::move<D>(u.get_deleter())) |
|
{} |
|
|
|
//!Effects: If get() == 0 there are no effects. Otherwise get_deleter()(get()). |
|
//! |
|
//!Throws: nothing. |
|
~unique_ptr() |
|
{ reset(); } |
|
|
|
// assignment |
|
|
|
//!Requires: Assignment of the deleter D from an rvalue D must not throw an exception. |
|
//! |
|
//!Effects: reset(u.release()) followed by a move assignment from u's deleter to |
|
//!this deleter. |
|
//! |
|
//!Postconditions: This unique_ptr now owns the pointer which u owned, and u no |
|
//!longer owns it. |
|
//! |
|
//!Returns: *this. |
|
//! |
|
//!Throws: nothing. |
|
unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u) |
|
{ |
|
reset(u.release()); |
|
ptr_.second() = boost::interprocess::move(u.get_deleter()); |
|
return *this; |
|
} |
|
|
|
//!Requires: Assignment of the deleter D from an rvalue D must not |
|
//!throw an exception. U* must be implicitly convertible to T*. |
|
//! |
|
//!Effects: reset(u.release()) followed by a move assignment from |
|
//!u's deleter to this deleter. If either D or E is |
|
//!a reference type, then the referenced lvalue deleter participates |
|
//!in the move assignment. |
|
//! |
|
//!Postconditions: This unique_ptr now owns the pointer which u owned, |
|
//!and u no longer owns it. |
|
//! |
|
//!Returns: *this. |
|
//! |
|
//!Throws: nothing. |
|
template <class U, class E> |
|
unique_ptr& operator=(BOOST_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u) |
|
{ |
|
reset(u.release()); |
|
ptr_.second() = boost::interprocess::move(u.get_deleter()); |
|
return *this; |
|
} |
|
|
|
//!Assigns from the literal 0 or NULL. |
|
//! |
|
//!Effects: reset(). |
|
//! |
|
//!Postcondition: get() == 0 |
|
//! |
|
//!Returns: *this. |
|
//! |
|
//!Throws: nothing. |
|
unique_ptr& operator=(int nat::*) |
|
{ |
|
reset(); |
|
return *this; |
|
} |
|
|
|
//!Requires: get() != 0. |
|
//!Returns: *get(). |
|
//!Throws: nothing. |
|
typename ipcdetail::add_reference<T>::type operator*() const |
|
{ return *ptr_.first(); } |
|
|
|
//!Requires: get() != 0. |
|
//!Returns: get(). |
|
//!Throws: nothing. |
|
pointer operator->() const |
|
{ return ptr_.first(); } |
|
|
|
//!Returns: The stored pointer. |
|
//!Throws: nothing. |
|
pointer get() const |
|
{ return ptr_.first(); } |
|
|
|
//!Returns: A reference to the stored deleter. |
|
//! |
|
//!Throws: nothing. |
|
deleter_reference get_deleter() |
|
{ return ptr_.second(); } |
|
|
|
//!Returns: A const reference to the stored deleter. |
|
//! |
|
//!Throws: nothing. |
|
deleter_const_reference get_deleter() const |
|
{ return ptr_.second(); } |
|
|
|
//!Returns: An unspecified value that, when used in boolean |
|
//!contexts, is equivalent to get() != 0. |
|
//! |
|
//!Throws: nothing. |
|
operator int nat::*() const |
|
{ return ptr_.first() ? &nat::for_bool_ : 0; } |
|
|
|
//!Postcondition: get() == 0. |
|
//! |
|
//!Returns: The value get() had at the start of the call to release. |
|
//! |
|
//!Throws: nothing. |
|
pointer release() |
|
{ |
|
pointer tmp = ptr_.first(); |
|
ptr_.first() = 0; |
|
return tmp; |
|
} |
|
|
|
//!Effects: If p == get() there are no effects. Otherwise get_deleter()(get()). |
|
//! |
|
//!Postconditions: get() == p. |
|
//! |
|
//!Throws: nothing. |
|
void reset(pointer p = 0) |
|
{ |
|
if (ptr_.first() != p){ |
|
if (ptr_.first()) |
|
ptr_.second()(ptr_.first()); |
|
ptr_.first() = p; |
|
} |
|
} |
|
|
|
//!Requires: The deleter D is Swappable and will not throw an exception under swap. |
|
//! |
|
//!Effects: The stored pointers of this and u are exchanged. |
|
//! The stored deleters are swapped (unqualified). |
|
//!Throws: nothing. |
|
void swap(unique_ptr& u) |
|
{ ptr_.swap(u.ptr_); } |
|
|
|
/// @cond |
|
private: |
|
boost::compressed_pair<pointer, D> ptr_; |
|
BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) |
|
template <class U, class E> unique_ptr(unique_ptr<U, E>&); |
|
template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0); |
|
|
|
template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&); |
|
template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&); |
|
/// @endcond |
|
}; |
|
/* |
|
template <class T, class D> |
|
class unique_ptr<T[], D> |
|
{ |
|
struct nat {int for_bool_;}; |
|
typedef typename ipcdetail::add_reference<D>::type deleter_reference; |
|
typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference; |
|
public: |
|
typedef T element_type; |
|
typedef D deleter_type; |
|
typedef typename ipcdetail::pointer_type<T, D>::type pointer; |
|
|
|
// constructors |
|
unique_ptr() : ptr_(pointer()) {} |
|
explicit unique_ptr(pointer p) : ptr_(p) {} |
|
unique_ptr(pointer p, typename if_< |
|
boost::is_reference<D>, |
|
D, |
|
typename ipcdetail::add_reference<const D>::type>::type d) |
|
: ptr_(p, d) {} |
|
unique_ptr(const unique_ptr& u) |
|
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {} |
|
|
|
// destructor |
|
~unique_ptr() {reset();} |
|
|
|
// assignment |
|
unique_ptr& operator=(const unique_ptr& cu) |
|
{ |
|
unique_ptr& u = const_cast<unique_ptr&>(cu); |
|
reset(u.release()); |
|
ptr_.second() = u.get_deleter(); |
|
return *this; |
|
} |
|
unique_ptr& operator=(int nat::*) |
|
{ |
|
reset(); |
|
return *this; |
|
} |
|
|
|
// observers |
|
typename ipcdetail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];} |
|
pointer get() const {return ptr_.first();} |
|
deleter_reference get_deleter() {return ptr_.second();} |
|
deleter_const_reference get_deleter() const {return ptr_.second();} |
|
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;} |
|
|
|
// modifiers |
|
pointer release() |
|
{ |
|
pointer tmp = ptr_.first(); |
|
ptr_.first() = 0; |
|
return tmp; |
|
} |
|
void reset(pointer p = 0) |
|
{ |
|
if (ptr_.first() != p) |
|
{ |
|
if (ptr_.first()) |
|
ptr_.second()(ptr_.first()); |
|
ptr_.first() = p; |
|
} |
|
} |
|
void swap(unique_ptr& u) {ptr_.swap(u.ptr_);} |
|
private: |
|
boost::compressed_pair<pointer, D> ptr_; |
|
|
|
template <class U, class E> unique_ptr(U p, E, |
|
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0); |
|
template <class U> explicit unique_ptr(U, |
|
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0); |
|
|
|
unique_ptr(unique_ptr&); |
|
template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0); |
|
|
|
unique_ptr& operator=(unique_ptr&); |
|
template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&); |
|
}; |
|
|
|
template <class T, class D, std::size_t N> |
|
class unique_ptr<T[N], D> |
|
{ |
|
struct nat {int for_bool_;}; |
|
typedef typename ipcdetail::add_reference<D>::type deleter_reference; |
|
typedef typename ipcdetail::add_reference<const D>::type deleter_const_reference; |
|
public: |
|
typedef T element_type; |
|
typedef D deleter_type; |
|
typedef typename ipcdetail::pointer_type<T, D>::type pointer; |
|
static const std::size_t size = N; |
|
|
|
// constructors |
|
unique_ptr() : ptr_(0) {} |
|
explicit unique_ptr(pointer p) : ptr_(p) {} |
|
unique_ptr(pointer p, typename if_< |
|
boost::is_reference<D>, |
|
D, |
|
typename ipcdetail::add_reference<const D>::type>::type d) |
|
: ptr_(p, d) {} |
|
unique_ptr(const unique_ptr& u) |
|
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {} |
|
|
|
// destructor |
|
~unique_ptr() {reset();} |
|
|
|
// assignment |
|
unique_ptr& operator=(const unique_ptr& cu) |
|
{ |
|
unique_ptr& u = const_cast<unique_ptr&>(cu); |
|
reset(u.release()); |
|
ptr_.second() = u.get_deleter(); |
|
return *this; |
|
} |
|
unique_ptr& operator=(int nat::*) |
|
{ |
|
reset(); |
|
return *this; |
|
} |
|
|
|
// observers |
|
typename ipcdetail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];} |
|
pointer get() const {return ptr_.first();} |
|
deleter_reference get_deleter() {return ptr_.second();} |
|
deleter_const_reference get_deleter() const {return ptr_.second();} |
|
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;} |
|
|
|
// modifiers |
|
pointer release() |
|
{ |
|
pointer tmp = ptr_.first(); |
|
ptr_.first() = 0; |
|
return tmp; |
|
} |
|
void reset(pointer p = 0) |
|
{ |
|
if (ptr_.first() != p) |
|
{ |
|
if (ptr_.first()) |
|
ptr_.second()(ptr_.first(), N); |
|
ptr_.first() = p; |
|
} |
|
} |
|
void swap(unique_ptr& u) {ptr_.swap(u.ptr_);} |
|
private: |
|
boost::compressed_pair<pointer, D> ptr_; |
|
|
|
template <class U, class E> unique_ptr(U p, E, |
|
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0); |
|
template <class U> explicit unique_ptr(U, |
|
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0); |
|
|
|
unique_ptr(unique_ptr&); |
|
template <class U> unique_ptr(U&, typename ipcdetail::unique_ptr_error<U>::type = 0); |
|
|
|
unique_ptr& operator=(unique_ptr&); |
|
template <class U> typename ipcdetail::unique_ptr_error<U>::type operator=(U&); |
|
}; |
|
*/ |
|
template <class T, class D> inline |
|
void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) |
|
{ x.swap(y); } |
|
|
|
template <class T1, class D1, class T2, class D2> inline |
|
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) |
|
{ return x.get() == y.get(); } |
|
|
|
template <class T1, class D1, class T2, class D2> inline |
|
bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) |
|
{ return x.get() != y.get(); } |
|
|
|
template <class T1, class D1, class T2, class D2> inline |
|
bool operator <(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) |
|
{ return x.get() < y.get(); } |
|
|
|
template <class T1, class D1, class T2, class D2> inline |
|
bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) |
|
{ return x.get() <= y.get(); } |
|
|
|
template <class T1, class D1, class T2, class D2> inline |
|
bool operator >(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) |
|
{ return x.get() > y.get(); } |
|
|
|
template <class T1, class D1, class T2, class D2> inline |
|
bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) |
|
{ return x.get() >= y.get(); } |
|
|
|
|
|
//!Returns the type of a unique pointer |
|
//!of type T with boost::interprocess::deleter deleter |
|
//!that can be constructed in the given managed segment type. |
|
template<class T, class ManagedMemory> |
|
struct managed_unique_ptr |
|
{ |
|
typedef unique_ptr |
|
< T |
|
, typename ManagedMemory::template deleter<T>::type |
|
> type; |
|
}; |
|
|
|
//!Returns an instance of a unique pointer constructed |
|
//!with boost::interproces::deleter from a pointer |
|
//!of type T that has been allocated in the passed managed segment |
|
template<class T, class ManagedMemory> |
|
inline typename managed_unique_ptr<T, ManagedMemory>::type |
|
make_managed_unique_ptr(T *constructed_object, ManagedMemory &managed_memory) |
|
{ |
|
return typename managed_unique_ptr<T, ManagedMemory>::type |
|
(constructed_object, managed_memory.template get_deleter<T>()); |
|
} |
|
|
|
} //namespace interprocess{ |
|
} //namespace boost{ |
|
|
|
#include <boost/interprocess/detail/config_end.hpp> |
|
|
|
#endif //#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED
|
|
|