////////////////////////////////////////////////////////////////////////////// | |
// 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 detail { | |
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 detail { | |
/// @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 detail::add_reference<D>::type deleter_reference; | |
typedef typename detail::add_reference<const D>::type deleter_const_reference; | |
/// @endcond | |
public: | |
typedef T element_type; | |
typedef D deleter_type; | |
typedef typename detail::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 detail::if_<detail::is_reference<D> | |
,D | |
,typename detail::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_INTERPROCESS_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_INTERPROCESS_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u, | |
typename detail::enable_if_c< | |
detail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value && | |
detail::is_convertible<E, D>::value && | |
( | |
!detail::is_reference<D>::value || | |
detail::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_INTERPROCESS_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_INTERPROCESS_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 detail::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_INTERPROCESS_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) | |
template <class U, class E> unique_ptr(unique_ptr<U, E>&); | |
template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0); | |
template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&); | |
template <class U> typename detail::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 detail::add_reference<D>::type deleter_reference; | |
typedef typename detail::add_reference<const D>::type deleter_const_reference; | |
public: | |
typedef T element_type; | |
typedef D deleter_type; | |
typedef typename detail::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 detail::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 detail::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 detail::unique_ptr_error<U>::type = 0); | |
unique_ptr& operator=(unique_ptr&); | |
template <class U> typename detail::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 detail::add_reference<D>::type deleter_reference; | |
typedef typename detail::add_reference<const D>::type deleter_const_reference; | |
public: | |
typedef T element_type; | |
typedef D deleter_type; | |
typedef typename detail::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 detail::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 detail::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 detail::unique_ptr_error<U>::type = 0); | |
unique_ptr& operator=(unique_ptr&); | |
template <class U> typename detail::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 |