Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@101: // (C) Copyright Ion Gaztanaga 2005-2014. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/interprocess for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP Chris@16: #define BOOST_INTERPROCESS_OFFSET_PTR_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include //alignment_of, aligned_storage Chris@16: #include Chris@101: #include Chris@16: Chris@16: //!\file Chris@16: //!Describes a smart pointer that stores the offset between this pointer and Chris@16: //!target pointee, called offset_ptr. Chris@16: Chris@16: namespace boost { Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@101: Chris@16: //Predeclarations Chris@16: template Chris@16: struct has_trivial_destructor; Chris@16: Chris@101: #endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@101: Chris@16: namespace interprocess { Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: namespace ipcdetail { Chris@16: Chris@16: template Chris@16: union offset_ptr_internal Chris@16: { Chris@16: explicit offset_ptr_internal(OffsetType off) Chris@16: : m_offset(off) Chris@16: {} Chris@16: OffsetType m_offset; //Distance between this object and pointee address Chris@101: typename ::boost::container::container_detail::aligned_storage Chris@16: < sizeof(OffsetType) Chris@16: , (OffsetAlignment == offset_type_alignment) ? Chris@101: ::boost::container::container_detail::alignment_of::value : OffsetAlignment Chris@16: >::type alignment_helper; Chris@16: }; Chris@16: Chris@16: //Note: using the address of a local variable to point to another address Chris@16: //is not standard conforming and this can be optimized-away by the compiler. Chris@16: //Non-inlining is a method to remain illegal but correct Chris@16: Chris@16: //Undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_XXX if your compiler can inline Chris@16: //this code without breaking the library Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // offset_ptr_to_raw_pointer Chris@16: // Chris@16: //////////////////////////////////////////////////////////////////////// Chris@16: #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR Chris@101: #if defined(_MSC_VER) && (_MSC_VER >= 1800) && (defined(_M_AMD64) || defined(_M_X64)) Chris@101: //Visual 2013 x64 optimizes more than we desire, so disable branchless option Chris@101: #else Chris@101: #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR Chris@101: #endif Chris@16: template Chris@16: #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR Chris@101: BOOST_NOINLINE Chris@16: #elif defined(NDEBUG) Chris@16: inline Chris@16: #endif Chris@16: void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, std::size_t offset) Chris@16: { Chris@16: typedef pointer_size_t_caster caster_t; Chris@16: #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR Chris@16: if(offset == 1){ Chris@16: return 0; Chris@16: } Chris@16: else{ Chris@16: const caster_t caster((void*)this_ptr); Chris@16: return caster_t(caster.size() + offset).pointer(); Chris@16: } Chris@16: #else Chris@16: const caster_t caster((void*)this_ptr); Chris@101: std::size_t target_offset = caster.size() + offset; Chris@101: std::size_t mask = -std::size_t(offset != 1); Chris@101: target_offset &= mask; Chris@101: return caster_t(target_offset).pointer(); Chris@16: #endif Chris@16: } Chris@16: Chris@16: #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR Chris@16: #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR Chris@16: #endif Chris@16: #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR Chris@16: #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR Chris@16: #endif Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // offset_ptr_to_offset Chris@16: // Chris@16: //////////////////////////////////////////////////////////////////////// Chris@16: #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF Chris@16: //Branchless seems slower in x86 Chris@16: #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF Chris@16: Chris@16: template Chris@16: #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF Chris@101: BOOST_NOINLINE Chris@16: #elif defined(NDEBUG) Chris@16: inline Chris@16: #endif Chris@16: std::size_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr) Chris@16: { Chris@16: typedef pointer_size_t_caster caster_t; Chris@16: #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF Chris@16: //offset == 1 && ptr != 0 is not legal for this pointer Chris@16: if(!ptr){ Chris@16: return 1; Chris@16: } Chris@16: else{ Chris@16: const caster_t this_caster((void*)this_ptr); Chris@16: const caster_t ptr_caster((void*)ptr); Chris@16: std::size_t offset = ptr_caster.size() - this_caster.size(); Chris@16: BOOST_ASSERT(offset != 1); Chris@16: return offset; Chris@16: } Chris@16: #else Chris@16: const caster_t this_caster((void*)this_ptr); Chris@16: const caster_t ptr_caster((void*)ptr); Chris@16: //std::size_t other = -std::size_t(ptr != 0); Chris@16: //std::size_t offset = (ptr_caster.size() - this_caster.size()) & other; Chris@16: //return offset + !other; Chris@16: // Chris@16: std::size_t offset = (ptr_caster.size() - this_caster.size() - 1) & -std::size_t(ptr != 0); Chris@16: return ++offset; Chris@16: #endif Chris@16: } Chris@16: Chris@16: #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF Chris@16: #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF Chris@16: #endif Chris@16: #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF Chris@16: #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF Chris@16: #endif Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // offset_ptr_to_offset_from_other Chris@16: // Chris@16: //////////////////////////////////////////////////////////////////////// Chris@16: #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER Chris@16: //Branchless seems slower in x86 Chris@16: #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER Chris@16: Chris@16: template Chris@16: #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER Chris@101: BOOST_NOINLINE Chris@16: #elif defined(NDEBUG) Chris@16: inline Chris@16: #endif Chris@16: std::size_t offset_ptr_to_offset_from_other Chris@16: (const volatile void *this_ptr, const volatile void *other_ptr, std::size_t other_offset) Chris@16: { Chris@16: typedef pointer_size_t_caster caster_t; Chris@16: #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER Chris@16: if(other_offset == 1){ Chris@16: return 1; Chris@16: } Chris@16: else{ Chris@16: const caster_t this_caster((void*)this_ptr); Chris@16: const caster_t other_caster((void*)other_ptr); Chris@16: std::size_t offset = other_caster.size() - this_caster.size() + other_offset; Chris@16: BOOST_ASSERT(offset != 1); Chris@16: return offset; Chris@16: } Chris@16: #else Chris@16: const caster_t this_caster((void*)this_ptr); Chris@16: const caster_t other_caster((void*)other_ptr); Chris@16: return ((other_caster.size() - this_caster.size()) & -std::size_t(other_offset != 1)) + other_offset; Chris@16: #endif Chris@16: } Chris@16: Chris@16: #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER Chris@16: #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER Chris@16: #endif Chris@16: #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER Chris@16: #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER Chris@16: #endif Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // Let's assume cast to void and cv cast don't change any target address Chris@16: // Chris@16: //////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct offset_ptr_maintains_address Chris@16: { Chris@16: static const bool value = ipcdetail::is_cv_same::value Chris@16: || ipcdetail::is_cv_same::value; Chris@16: }; Chris@16: Chris@16: } //namespace ipcdetail { Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: //!A smart pointer that stores the offset between between the pointer and the Chris@16: //!the object it points. This allows offset allows special properties, since Chris@16: //!the pointer is independent from the address address of the pointee, if the Chris@16: //!pointer and the pointee are still separated by the same offset. This feature Chris@16: //!converts offset_ptr in a smart pointer that can be placed in shared memory and Chris@16: //!memory mapped files mapped in different addresses in every process. Chris@101: //! Chris@101: //! \tparam PointedType The type of the pointee. Chris@101: //! \tparam DifferenceType A signed integer type that can represent the arithmetic operations on the pointer Chris@101: //! \tparam OffsetType An unsigned integer type that can represent the Chris@101: //! distance between two pointers reinterpret_cast-ed as unsigned integers. In general this type Chris@101: //! should be at least of the same size of std::uintptr_t. In some systems it's possible to communicate Chris@101: //! between 32 and 64 bit processes using 64 bit offsets. Chris@101: //! \tparam OffsetAlignment Alignment of the OffsetType stored inside. In some systems might be necessary Chris@101: //! to align it to 64 bits in order to communicate 32 and 64 bit processes using 64 bit offsets. Chris@16: template Chris@16: class offset_ptr Chris@16: { Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: typedef offset_ptr self_t; Chris@16: void unspecified_bool_type_func() const {} Chris@16: typedef void (self_t::*unspecified_bool_type)() const; Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: public: Chris@16: typedef PointedType element_type; Chris@16: typedef PointedType * pointer; Chris@16: typedef typename ipcdetail:: Chris@16: add_reference::type reference; Chris@16: typedef typename ipcdetail:: Chris@16: remove_volatile::type Chris@16: >::type value_type; Chris@16: typedef DifferenceType difference_type; Chris@16: typedef std::random_access_iterator_tag iterator_category; Chris@16: typedef OffsetType offset_type; Chris@16: Chris@16: public: //Public Functions Chris@16: Chris@16: //!Default constructor (null pointer). Chris@16: //!Never throws. Chris@16: offset_ptr() Chris@16: : internal(1) Chris@16: {} Chris@16: Chris@16: //!Constructor from raw pointer (allows "0" pointer conversion). Chris@16: //!Never throws. Chris@16: offset_ptr(pointer ptr) Chris@16: : internal(static_cast(ipcdetail::offset_ptr_to_offset<0>(ptr, this))) Chris@16: {} Chris@16: Chris@16: //!Constructor from other pointer. Chris@16: //!Never throws. Chris@16: template Chris@16: offset_ptr( T *ptr Chris@16: , typename ipcdetail::enable_if< ipcdetail::is_convertible >::type * = 0) Chris@16: : internal(static_cast Chris@16: (ipcdetail::offset_ptr_to_offset<0>(static_cast(ptr), this))) Chris@16: {} Chris@16: Chris@16: //!Constructor from other offset_ptr Chris@16: //!Never throws. Chris@16: offset_ptr(const offset_ptr& ptr) Chris@16: : internal(static_cast Chris@16: (ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset))) Chris@16: {} Chris@16: Chris@16: //!Constructor from other offset_ptr. If pointers of pointee types are Chris@16: //!convertible, offset_ptrs will be convertibles. Never throws. Chris@16: template Chris@16: offset_ptr( const offset_ptr &ptr Chris@16: #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@101: , typename ipcdetail::enable_if_c< ipcdetail::is_convertible::value Chris@16: && ipcdetail::offset_ptr_maintains_address::value Chris@16: >::type * = 0 Chris@16: #endif Chris@16: ) Chris@16: : internal(static_cast Chris@16: (ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset()))) Chris@16: {} Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: //!Constructor from other offset_ptr. If pointers of pointee types are Chris@16: //!convertible, offset_ptrs will be convertibles. Never throws. Chris@16: template Chris@16: offset_ptr( const offset_ptr &ptr Chris@16: , typename ipcdetail::enable_if_c< ipcdetail::is_convertible::value Chris@16: && !ipcdetail::offset_ptr_maintains_address::value Chris@16: >::type * = 0) Chris@16: : internal(static_cast Chris@16: (ipcdetail::offset_ptr_to_offset<0>(static_cast(ptr.get()), this))) Chris@16: {} Chris@16: Chris@16: #endif Chris@16: Chris@16: //!Emulates static_cast operator. Chris@16: //!Never throws. Chris@16: template Chris@16: offset_ptr(const offset_ptr & r, ipcdetail::static_cast_tag) Chris@16: : internal(static_cast Chris@16: (ipcdetail::offset_ptr_to_offset<0>(static_cast(r.get()), this))) Chris@16: {} Chris@16: Chris@16: //!Emulates const_cast operator. Chris@16: //!Never throws. Chris@16: template Chris@16: offset_ptr(const offset_ptr & r, ipcdetail::const_cast_tag) Chris@16: : internal(static_cast Chris@16: (ipcdetail::offset_ptr_to_offset<0>(const_cast(r.get()), this))) Chris@16: {} Chris@16: Chris@16: //!Emulates dynamic_cast operator. Chris@16: //!Never throws. Chris@16: template Chris@16: offset_ptr(const offset_ptr & r, ipcdetail::dynamic_cast_tag) Chris@16: : internal(static_cast Chris@16: (ipcdetail::offset_ptr_to_offset<0>(dynamic_cast(r.get()), this))) Chris@16: {} Chris@16: Chris@16: //!Emulates reinterpret_cast operator. Chris@16: //!Never throws. Chris@16: template Chris@16: offset_ptr(const offset_ptr & r, ipcdetail::reinterpret_cast_tag) Chris@16: : internal(static_cast Chris@16: (ipcdetail::offset_ptr_to_offset<0>(reinterpret_cast(r.get()), this))) Chris@16: {} Chris@16: Chris@16: //!Obtains raw pointer from offset. Chris@16: //!Never throws. Chris@16: pointer get() const Chris@16: { return (pointer)ipcdetail::offset_ptr_to_raw_pointer<0>(this, this->internal.m_offset); } Chris@16: Chris@16: offset_type get_offset() const Chris@16: { return this->internal.m_offset; } Chris@16: Chris@16: //!Pointer-like -> operator. It can return 0 pointer. Chris@16: //!Never throws. Chris@16: pointer operator->() const Chris@16: { return this->get(); } Chris@16: Chris@16: //!Dereferencing operator, if it is a null offset_ptr behavior Chris@16: //! is undefined. Never throws. Chris@16: reference operator* () const Chris@16: { Chris@16: pointer p = this->get(); Chris@16: reference r = *p; Chris@16: return r; Chris@16: } Chris@16: Chris@16: //!Indexing operator. Chris@16: //!Never throws. Chris@16: reference operator[](difference_type idx) const Chris@16: { return this->get()[idx]; } Chris@16: Chris@16: //!Assignment from pointer (saves extra conversion). Chris@16: //!Never throws. Chris@16: offset_ptr& operator= (pointer from) Chris@16: { Chris@16: this->internal.m_offset = Chris@16: static_cast(ipcdetail::offset_ptr_to_offset<0>(from, this)); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //!Assignment from other offset_ptr. Chris@16: //!Never throws. Chris@16: offset_ptr& operator= (const offset_ptr & ptr) Chris@16: { Chris@16: this->internal.m_offset = Chris@16: static_cast(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset)); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //!Assignment from related offset_ptr. If pointers of pointee types Chris@16: //! are assignable, offset_ptrs will be assignable. Never throws. Chris@16: template Chris@16: #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: typename ipcdetail::enable_if_c< ipcdetail::is_convertible::value Chris@16: && ipcdetail::offset_ptr_maintains_address::value Chris@16: , offset_ptr&>::type Chris@16: #else Chris@16: offset_ptr& Chris@16: #endif Chris@16: operator= (const offset_ptr &ptr) Chris@16: { Chris@16: this->internal.m_offset = Chris@16: static_cast(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset())); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: template Chris@101: typename ipcdetail::enable_if_c::value Chris@16: && !ipcdetail::offset_ptr_maintains_address::value Chris@16: , offset_ptr&>::type Chris@16: operator= (const offset_ptr &ptr) Chris@16: { Chris@16: this->internal.m_offset = Chris@16: static_cast(ipcdetail::offset_ptr_to_offset<0>(static_cast(ptr.get()), this)); Chris@16: return *this; Chris@16: } Chris@16: #endif Chris@16: Chris@16: //!offset_ptr += difference_type. Chris@16: //!Never throws. Chris@16: offset_ptr &operator+= (difference_type offset) Chris@16: { this->inc_offset(offset * sizeof (PointedType)); return *this; } Chris@16: Chris@16: //!offset_ptr -= difference_type. Chris@16: //!Never throws. Chris@16: offset_ptr &operator-= (difference_type offset) Chris@16: { this->dec_offset(offset * sizeof (PointedType)); return *this; } Chris@16: Chris@16: //!++offset_ptr. Chris@16: //!Never throws. Chris@16: offset_ptr& operator++ (void) Chris@16: { this->inc_offset(sizeof (PointedType)); return *this; } Chris@16: Chris@16: //!offset_ptr++. Chris@16: //!Never throws. Chris@16: offset_ptr operator++ (int) Chris@16: { Chris@16: offset_ptr tmp(*this); Chris@16: this->inc_offset(sizeof (PointedType)); Chris@16: return tmp; Chris@16: } Chris@16: Chris@16: //!--offset_ptr. Chris@16: //!Never throws. Chris@16: offset_ptr& operator-- (void) Chris@16: { this->dec_offset(sizeof (PointedType)); return *this; } Chris@16: Chris@16: //!offset_ptr--. Chris@16: //!Never throws. Chris@16: offset_ptr operator-- (int) Chris@16: { Chris@16: offset_ptr tmp(*this); Chris@16: this->dec_offset(sizeof (PointedType)); Chris@16: return tmp; Chris@16: } Chris@16: Chris@16: //!safe bool conversion operator. Chris@16: //!Never throws. Chris@16: operator unspecified_bool_type() const Chris@16: { return this->internal.m_offset != 1? &self_t::unspecified_bool_type_func : 0; } Chris@16: Chris@16: //!Not operator. Not needed in theory, but improves portability. Chris@16: //!Never throws Chris@16: bool operator! () const Chris@16: { return this->internal.m_offset == 1; } Chris@16: Chris@16: //!Compatibility with pointer_traits Chris@16: //! Chris@16: template Chris@16: struct rebind Chris@16: { typedef offset_ptr other; }; Chris@16: Chris@16: //!Compatibility with pointer_traits Chris@16: //! Chris@16: static offset_ptr pointer_to(reference r) Chris@16: { return offset_ptr(&r); } Chris@16: Chris@16: //!difference_type + offset_ptr Chris@16: //!operation Chris@16: friend offset_ptr operator+(difference_type diff, offset_ptr right) Chris@16: { right += diff; return right; } Chris@16: Chris@16: //!offset_ptr + difference_type Chris@16: //!operation Chris@16: friend offset_ptr operator+(offset_ptr left, difference_type diff) Chris@16: { left += diff; return left; } Chris@16: Chris@16: //!offset_ptr - diff Chris@16: //!operation Chris@16: friend offset_ptr operator-(offset_ptr left, difference_type diff) Chris@16: { left -= diff; return left; } Chris@16: Chris@16: //!offset_ptr - diff Chris@16: //!operation Chris@16: friend offset_ptr operator-(difference_type diff, offset_ptr right) Chris@16: { right -= diff; return right; } Chris@16: Chris@16: //!offset_ptr - offset_ptr Chris@16: //!operation Chris@16: friend difference_type operator-(const offset_ptr &pt, const offset_ptr &pt2) Chris@16: { return difference_type(pt.get()- pt2.get()); } Chris@16: Chris@16: //Comparison Chris@16: friend bool operator== (const offset_ptr &pt1, const offset_ptr &pt2) Chris@16: { return pt1.get() == pt2.get(); } Chris@16: Chris@16: friend bool operator!= (const offset_ptr &pt1, const offset_ptr &pt2) Chris@16: { return pt1.get() != pt2.get(); } Chris@16: Chris@16: friend bool operator<(const offset_ptr &pt1, const offset_ptr &pt2) Chris@16: { return pt1.get() < pt2.get(); } Chris@16: Chris@16: friend bool operator<=(const offset_ptr &pt1, const offset_ptr &pt2) Chris@16: { return pt1.get() <= pt2.get(); } Chris@16: Chris@16: friend bool operator>(const offset_ptr &pt1, const offset_ptr &pt2) Chris@16: { return pt1.get() > pt2.get(); } Chris@16: Chris@16: friend bool operator>=(const offset_ptr &pt1, const offset_ptr &pt2) Chris@16: { return pt1.get() >= pt2.get(); } Chris@16: Chris@16: //Comparison to raw ptr to support literal 0 Chris@16: friend bool operator== (pointer pt1, const offset_ptr &pt2) Chris@16: { return pt1 == pt2.get(); } Chris@16: Chris@16: friend bool operator!= (pointer pt1, const offset_ptr &pt2) Chris@16: { return pt1 != pt2.get(); } Chris@16: Chris@16: friend bool operator<(pointer pt1, const offset_ptr &pt2) Chris@16: { return pt1 < pt2.get(); } Chris@16: Chris@16: friend bool operator<=(pointer pt1, const offset_ptr &pt2) Chris@16: { return pt1 <= pt2.get(); } Chris@16: Chris@16: friend bool operator>(pointer pt1, const offset_ptr &pt2) Chris@16: { return pt1 > pt2.get(); } Chris@16: Chris@16: friend bool operator>=(pointer pt1, const offset_ptr &pt2) Chris@16: { return pt1 >= pt2.get(); } Chris@16: Chris@16: //Comparison Chris@16: friend bool operator== (const offset_ptr &pt1, pointer pt2) Chris@16: { return pt1.get() == pt2; } Chris@16: Chris@16: friend bool operator!= (const offset_ptr &pt1, pointer pt2) Chris@16: { return pt1.get() != pt2; } Chris@16: Chris@16: friend bool operator<(const offset_ptr &pt1, pointer pt2) Chris@16: { return pt1.get() < pt2; } Chris@16: Chris@16: friend bool operator<=(const offset_ptr &pt1, pointer pt2) Chris@16: { return pt1.get() <= pt2; } Chris@16: Chris@16: friend bool operator>(const offset_ptr &pt1, pointer pt2) Chris@16: { return pt1.get() > pt2; } Chris@16: Chris@16: friend bool operator>=(const offset_ptr &pt1, pointer pt2) Chris@16: { return pt1.get() >= pt2; } Chris@16: Chris@16: friend void swap(offset_ptr &left, offset_ptr &right) Chris@16: { Chris@16: pointer ptr = right.get(); Chris@16: right = left; Chris@16: left = ptr; Chris@16: } Chris@16: Chris@16: private: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: void inc_offset(DifferenceType bytes) Chris@16: { internal.m_offset += bytes; } Chris@16: Chris@16: void dec_offset(DifferenceType bytes) Chris@16: { internal.m_offset -= bytes; } Chris@16: Chris@16: ipcdetail::offset_ptr_internal internal; Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: }; Chris@16: Chris@16: //!operator<< Chris@16: //!for offset ptr Chris@16: template Chris@16: inline std::basic_ostream & operator<< Chris@16: (std::basic_ostream & os, offset_ptr const & p) Chris@16: { return os << p.get_offset(); } Chris@16: Chris@16: //!operator>> Chris@16: //!for offset ptr Chris@16: template Chris@16: inline std::basic_istream & operator>> Chris@16: (std::basic_istream & is, offset_ptr & p) Chris@16: { return is >> p.get_offset(); } Chris@16: Chris@16: //!Simulation of static_cast between pointers. Never throws. Chris@16: template Chris@16: inline boost::interprocess::offset_ptr Chris@16: static_pointer_cast(const boost::interprocess::offset_ptr & r) Chris@16: { Chris@16: return boost::interprocess::offset_ptr Chris@16: (r, boost::interprocess::ipcdetail::static_cast_tag()); Chris@16: } Chris@16: Chris@16: //!Simulation of const_cast between pointers. Never throws. Chris@16: template Chris@16: inline boost::interprocess::offset_ptr Chris@16: const_pointer_cast(const boost::interprocess::offset_ptr & r) Chris@16: { Chris@16: return boost::interprocess::offset_ptr Chris@16: (r, boost::interprocess::ipcdetail::const_cast_tag()); Chris@16: } Chris@16: Chris@16: //!Simulation of dynamic_cast between pointers. Never throws. Chris@16: template Chris@16: inline boost::interprocess::offset_ptr Chris@16: dynamic_pointer_cast(const boost::interprocess::offset_ptr & r) Chris@16: { Chris@16: return boost::interprocess::offset_ptr Chris@16: (r, boost::interprocess::ipcdetail::dynamic_cast_tag()); Chris@16: } Chris@16: Chris@16: //!Simulation of reinterpret_cast between pointers. Never throws. Chris@16: template Chris@16: inline boost::interprocess::offset_ptr Chris@16: reinterpret_pointer_cast(const boost::interprocess::offset_ptr & r) Chris@16: { Chris@16: return boost::interprocess::offset_ptr Chris@16: (r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); Chris@16: } Chris@16: Chris@16: } //namespace interprocess { Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: Chris@101: ///has_trivial_destructor<> == true_type specialization for optimizations Chris@16: template Chris@101: struct has_trivial_destructor< ::boost::interprocess::offset_ptr > Chris@16: { Chris@16: static const bool value = true; Chris@16: }; Chris@16: Chris@101: namespace move_detail { Chris@101: Chris@16: ///has_trivial_destructor<> == true_type specialization for optimizations Chris@16: template Chris@101: struct is_trivially_destructible< ::boost::interprocess::offset_ptr > Chris@16: { Chris@16: static const bool value = true; Chris@16: }; Chris@16: Chris@101: } //namespace move_detail { Chris@16: Chris@16: namespace interprocess { Chris@16: Chris@16: //!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr. Chris@16: //!Never throws. Chris@16: template Chris@16: inline T * to_raw_pointer(boost::interprocess::offset_ptr const & p) Chris@16: { return ipcdetail::to_raw_pointer(p); } Chris@16: Chris@16: } //namespace interprocess Chris@16: Chris@16: Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: } //namespace boost { Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: Chris@16: namespace boost{ Chris@16: Chris@16: //This is to support embedding a bit in the pointer Chris@16: //for intrusive containers, saving space Chris@16: namespace intrusive { Chris@16: Chris@16: //Predeclaration to avoid including header Chris@16: template Chris@16: struct max_pointer_plus_bits; Chris@16: Chris@16: template Chris@16: struct max_pointer_plus_bits, OffsetAlignment> Chris@16: { Chris@16: //The offset ptr can embed one bit less than the alignment since it Chris@16: //uses offset == 1 to store the null pointer. Chris@16: static const std::size_t value = ::boost::interprocess::ipcdetail::ls_zeros::value - 1; Chris@16: }; Chris@16: Chris@16: //Predeclaration Chris@16: template Chris@16: struct pointer_plus_bits; Chris@16: Chris@16: template Chris@16: struct pointer_plus_bits, NumBits> Chris@16: { Chris@16: typedef boost::interprocess::offset_ptr pointer; Chris@16: typedef ::boost::interprocess::pointer_size_t_caster caster_t; Chris@16: //Bits are stored in the lower bits of the pointer except the LSB, Chris@16: //because this bit is used to represent the null pointer. Chris@16: static const std::size_t Mask = ((std::size_t(1) << NumBits) - 1) << 1u; Chris@16: Chris@16: static pointer get_pointer(const pointer &n) Chris@16: { Chris@16: caster_t caster(n.get()); Chris@16: return pointer(caster_t(caster.size() & ~Mask).pointer()); Chris@16: } Chris@16: Chris@16: static void set_pointer(pointer &n, const pointer &p) Chris@16: { Chris@16: caster_t n_caster(n.get()); Chris@16: caster_t p_caster(p.get()); Chris@16: BOOST_ASSERT(0 == (p_caster.size() & Mask)); Chris@16: n = caster_t(p_caster.size() | (n_caster.size() & Mask)).pointer(); Chris@16: } Chris@16: Chris@16: static std::size_t get_bits(const pointer &n) Chris@16: { return (caster_t(n.get()).size() & Mask) >> 1u; } Chris@16: Chris@16: static void set_bits(pointer &n, std::size_t b) Chris@16: { Chris@16: BOOST_ASSERT(b < (std::size_t(1) << NumBits)); Chris@16: caster_t n_caster(n.get()); Chris@16: n = caster_t((n_caster.size() & ~Mask) | (b << 1u)).pointer(); Chris@16: } Chris@16: }; Chris@16: Chris@16: } //namespace intrusive Chris@16: Chris@16: //Predeclaration Chris@16: template Chris@16: struct pointer_to_other; Chris@16: Chris@16: //Backwards compatibility with pointer_to_other Chris@16: template Chris@16: struct pointer_to_other Chris@16: < ::boost::interprocess::offset_ptr, U > Chris@16: { Chris@16: typedef ::boost::interprocess::offset_ptr type; Chris@16: }; Chris@16: Chris@16: } //namespace boost{ Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: #include Chris@16: Chris@16: #endif //#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP