| ////////////////////////////////////////////////////////////////////////////// |
| // 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 |