////////////////////////////////////////////////////////////////////////////// // 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 #include #include #include #include #include #include #include #include #include #include #include //!\file //!Describes the smart pointer unique_ptr namespace boost{ namespace interprocess{ /// @cond template class unique_ptr; namespace detail { template struct unique_ptr_error; template struct unique_ptr_error > { typedef unique_ptr 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 unique_ptr { /// @cond struct nat {int for_bool_;}; typedef typename detail::add_reference::type deleter_reference; typedef typename detail::add_reference::type deleter_const_reference; /// @endcond public: typedef T element_type; typedef D deleter_type; typedef typename detail::pointer_type::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_ ,D ,typename detail::add_reference::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 //!std::forward. —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. #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE unique_ptr(detail::moved_object u) : ptr_(u.get().release(), move(u.get().get_deleter())) {} #else unique_ptr(unique_ptr &&u) : ptr_(u.release(), forward(u.get_deleter())) {} #endif //!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::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. #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template unique_ptr(const detail::moved_object >& u, typename detail::enable_if_c< detail::is_convertible::pointer, pointer>::value && detail::is_convertible::value && ( !detail::is_reference::value || detail::is_same::value ) , nat >::type = nat()) : ptr_(const_cast&>(u.get()).release(), move(u.get().get_deleter())) {} #else template unique_ptr(unique_ptr && u, typename boost::enable_if_c< detail::is_convertible::pointer, pointer>::value && detail::is_convertible::value && ( !detail::is_reference::value || detail::is_same::value ) , nat >::type = nat()) : ptr_(const_cast&>(u).release(), forward(u.get_deleter())) {} #endif //!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. #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE unique_ptr& operator=(const detail::moved_object& u) { reset(u.get().release()); ptr_.second() = move(u.get().get_deleter()); return *this; } #else unique_ptr(unique_ptr && u) { reset(u.release()); ptr_.second() = move(u.get_deleter()); return *this; } #endif //!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 #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE unique_ptr& operator=(const detail::moved_object >& mu) { reset(mu.get().release()); ptr_.second() = move(mu.get().get_deleter()); return *this; } #else unique_ptr(unique_ptr && u) { reset(u.release()); ptr_.second() = move(u.get_deleter()); return *this; } #endif //!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::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 swap’d (unqualified). //! //!Throws: nothing. #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(unique_ptr& u) { ptr_.swap(u.ptr_); } void swap(detail::moved_object mu) { ptr_.swap(mu.get().ptr_); } #else void swap(unique_ptr&&u) { ptr_.swap(u.ptr_); } #endif /// @cond private: boost::compressed_pair ptr_; //This private constructor avoids moving from non-const lvalues unique_ptr(const unique_ptr&); template unique_ptr(unique_ptr&); template unique_ptr(U&, typename detail::unique_ptr_error::type = 0); unique_ptr& operator=(unique_ptr&); template unique_ptr& operator=(unique_ptr&); template typename detail::unique_ptr_error::type operator=(U&); /// @endcond }; /* template class unique_ptr { struct nat {int for_bool_;}; typedef typename detail::add_reference::type deleter_reference; typedef typename detail::add_reference::type deleter_const_reference; public: typedef T element_type; typedef D deleter_type; typedef typename detail::pointer_type::type pointer; // constructors unique_ptr() : ptr_(pointer()) {} explicit unique_ptr(pointer p) : ptr_(p) {} unique_ptr(pointer p, typename if_< boost::is_reference, D, typename detail::add_reference::type>::type d) : ptr_(p, d) {} unique_ptr(const unique_ptr& u) : ptr_(const_cast(u).release(), u.get_deleter()) {} // destructor ~unique_ptr() {reset();} // assignment unique_ptr& operator=(const unique_ptr& cu) { unique_ptr& u = const_cast(cu); reset(u.release()); ptr_.second() = u.get_deleter(); return *this; } unique_ptr& operator=(int nat::*) { reset(); return *this; } // observers typename detail::add_reference::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 ptr_; template unique_ptr(U p, E, typename boost::enable_if >::type* = 0); template explicit unique_ptr(U, typename boost::enable_if >::type* = 0); unique_ptr(unique_ptr&); template unique_ptr(U&, typename detail::unique_ptr_error::type = 0); unique_ptr& operator=(unique_ptr&); template typename detail::unique_ptr_error::type operator=(U&); }; template class unique_ptr { struct nat {int for_bool_;}; typedef typename detail::add_reference::type deleter_reference; typedef typename detail::add_reference::type deleter_const_reference; public: typedef T element_type; typedef D deleter_type; typedef typename detail::pointer_type::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, typename detail::add_reference::type>::type d) : ptr_(p, d) {} unique_ptr(const unique_ptr& u) : ptr_(const_cast(u).release(), u.get_deleter()) {} // destructor ~unique_ptr() {reset();} // assignment unique_ptr& operator=(const unique_ptr& cu) { unique_ptr& u = const_cast(cu); reset(u.release()); ptr_.second() = u.get_deleter(); return *this; } unique_ptr& operator=(int nat::*) { reset(); return *this; } // observers typename detail::add_reference::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 ptr_; template unique_ptr(U p, E, typename boost::enable_if >::type* = 0); template explicit unique_ptr(U, typename boost::enable_if >::type* = 0); unique_ptr(unique_ptr&); template unique_ptr(U&, typename detail::unique_ptr_error::type = 0); unique_ptr& operator=(unique_ptr&); template typename detail::unique_ptr_error::type operator=(U&); }; */ template inline void swap(unique_ptr& x, unique_ptr& y) { x.swap(y); } template inline bool operator==(const unique_ptr& x, const unique_ptr& y) { return x.get() == y.get(); } template inline bool operator!=(const unique_ptr& x, const unique_ptr& y) { return x.get() != y.get(); } template inline bool operator <(const unique_ptr& x, const unique_ptr& y) { return x.get() < y.get(); } template inline bool operator<=(const unique_ptr& x, const unique_ptr& y) { return x.get() <= y.get(); } template inline bool operator >(const unique_ptr& x, const unique_ptr& y) { return x.get() > y.get(); } template inline bool operator>=(const unique_ptr& x, const unique_ptr& y) { return x.get() >= y.get(); } /// @cond //!This class has move constructor template struct is_movable > { enum { value = true }; }; /// @endcond //!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 struct managed_unique_ptr { typedef unique_ptr < T , typename ManagedMemory::template deleter::type > type; }; //!Returns an instance of the a unique pointer constructed //!with boost::interproces::deleter from a pointer //!of type T that has been allocated in the passed managed segment template inline typename detail::return_type ::type >::type make_managed_unique_ptr(T *constructed_object, ManagedMemory &managed_memory) { typename managed_unique_ptr::type to_return ( constructed_object , managed_memory.template get_deleter() ); return to_return; } } //namespace interprocess{ } //namespace boost{ #include #endif //#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED