123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- //////////////////////////////////////////////////////////////////////////////
- // 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-2012. 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/move/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;};
- struct nat2 {int for_nullptr;};
- typedef int nat2::*nullptr_t;
- 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::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::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_BEG unique_ptr<U, E> BOOST_RV_REF_END 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::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::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_BEG unique_ptr<U, E> BOOST_RV_REF_END u)
- {
- reset(u.release());
- ptr_.second() = boost::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=(nullptr_t)
- {
- 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
|