From 892e541c177d5a87bfa8e8765f967cd70e9f545a Mon Sep 17 00:00:00 2001 From: Tobias Reh Date: Wed, 4 Jan 2017 14:38:34 +0100 Subject: [PATCH 1/2] Enable explicit construction of offset_ptr from offset_ptr With 'enable_if' and 'explicit', care is taken to behave just as 'normal' pointers. --- include/boost/interprocess/offset_ptr.hpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/include/boost/interprocess/offset_ptr.hpp b/include/boost/interprocess/offset_ptr.hpp index fca444ea..e40be464 100644 --- a/include/boost/interprocess/offset_ptr.hpp +++ b/include/boost/interprocess/offset_ptr.hpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -270,8 +271,8 @@ class offset_ptr (ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset))) {} - //!Constructor from other offset_ptr. If pointers of pointee types are - //!convertible, offset_ptrs will be convertibles. Never throws. + //!Constructor from other offset_ptr. Only takes part in overload resolution + //!if T2* is convertible to PointedType*. Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr &ptr #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED @@ -284,8 +285,6 @@ class offset_ptr #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - //!Constructor from other offset_ptr. If pointers of pointee types are - //!convertible, offset_ptrs will be convertibles. Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr &ptr , typename ipcdetail::enable_if_convertible_unequal_address::type* = 0) BOOST_NOEXCEPT @@ -295,6 +294,20 @@ class offset_ptr #endif + //!Constructor from other offset_ptr. Only takes part in overload resolution + //!if PointedType* is constructible from T2* other than via a conversion (e.g. cast to a derived class). Never throws. + template + BOOST_INTERPROCESS_FORCEINLINE explicit offset_ptr(const offset_ptr &ptr + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + , typename ipcdetail::enable_if_c< + !::boost::is_convertible::value && ::boost::is_constructible::value + >::type * = 0 + #endif + ) BOOST_NOEXCEPT + : internal(static_cast + (ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this))) + {} + //!Emulates static_cast operator. //!Never throws. template From f78a2e2ffd1ff12d2da520d1a908b728750e3694 Mon Sep 17 00:00:00 2001 From: Tobias Reh Date: Wed, 11 Jan 2017 13:46:52 +0100 Subject: [PATCH 2/2] Restore possibility to communicate between 32 and 64 bit processes using 64 bit offsets If the pointed adress is 128 bytes lower than 'this', we have (a) 32bit uintptr_t, 32bit OffsetType: offset = 0x ffffff80 (b) 64bit uintptr_t, 64bit OffsetType: offset = 0xffffffffffffff80 (c) 32bit uintptr_t, 64bit OffsetType: offset = 0x00000000ffffff80 If we read (c) from an 64bit process, it gets interpreted as 4294967232 bytes forward rather than 128 bytes backward. This commit solves the problem by ajusting the offset representation of (c) to match (b). For the 32bit process itself (c) this makes no difference, as the most significant 4 bytes get truncated anyway when convertig to a pointer. Note: For the default OffsetType=uintptr_t this change is only syntactical. --- include/boost/interprocess/detail/utilities.hpp | 24 +++--- include/boost/interprocess/offset_ptr.hpp | 105 +++++++++++------------- 2 files changed, 61 insertions(+), 68 deletions(-) diff --git a/include/boost/interprocess/detail/utilities.hpp b/include/boost/interprocess/detail/utilities.hpp index e1be2f15..c1b23423 100644 --- a/include/boost/interprocess/detail/utilities.hpp +++ b/include/boost/interprocess/detail/utilities.hpp @@ -156,29 +156,29 @@ BOOST_INTERPROCESS_FORCEINLINE bool size_overflows(SizeType count) return multiplication_overflows(SizeType(SztSizeOfType), count); } -template -class pointer_uintptr_caster; +template +class pointer_offset_caster; -template -class pointer_uintptr_caster +template +class pointer_offset_caster { public: - BOOST_INTERPROCESS_FORCEINLINE explicit pointer_uintptr_caster(uintptr_t sz) - : m_uintptr(sz) + BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(OffsetType offset) + : m_offset(offset) {} - BOOST_INTERPROCESS_FORCEINLINE explicit pointer_uintptr_caster(const volatile T *p) - : m_uintptr(reinterpret_cast(p)) + BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(const volatile T *p) + : m_offset(reinterpret_cast(p)) {} - BOOST_INTERPROCESS_FORCEINLINE uintptr_t uintptr() const - { return m_uintptr; } + BOOST_INTERPROCESS_FORCEINLINE OffsetType offset() const + { return m_offset; } BOOST_INTERPROCESS_FORCEINLINE T* pointer() const - { return reinterpret_cast(m_uintptr); } + { return reinterpret_cast(m_offset); } private: - uintptr_t m_uintptr; + OffsetType m_offset; }; diff --git a/include/boost/interprocess/offset_ptr.hpp b/include/boost/interprocess/offset_ptr.hpp index e40be464..8ee8d5a6 100644 --- a/include/boost/interprocess/offset_ptr.hpp +++ b/include/boost/interprocess/offset_ptr.hpp @@ -24,6 +24,8 @@ #include #include +#include +#include #include #include @@ -56,6 +58,7 @@ namespace ipcdetail { union offset_ptr_internal { BOOST_STATIC_ASSERT(sizeof(OffsetType) >= sizeof(uintptr_t)); + BOOST_STATIC_ASSERT(boost::is_integral::value && boost::is_unsigned::value); explicit offset_ptr_internal(OffsetType off) : m_offset(off) @@ -82,20 +85,21 @@ namespace ipcdetail { // //////////////////////////////////////////////////////////////////////// #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR - BOOST_INTERPROCESS_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, uintptr_t offset) + template + BOOST_INTERPROCESS_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, OffsetType offset) { - typedef pointer_uintptr_caster caster_t; + typedef pointer_offset_caster caster_t; #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR if(offset == 1){ return 0; } else{ - return caster_t(caster_t(this_ptr).uintptr() + offset).pointer(); + return caster_t(caster_t(this_ptr).offset() + offset).pointer(); } #else - uintptr_t mask = offset == 1; + OffsetType mask = offset == 1; --mask; - uintptr_t target_offset = caster_t(this_ptr).uintptr() + offset; + OffsetType target_offset = caster_t(this_ptr).offset() + offset; target_offset &= mask; return caster_t(target_offset).pointer(); #endif @@ -107,27 +111,28 @@ namespace ipcdetail { // //////////////////////////////////////////////////////////////////////// #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF - BOOST_INTERPROCESS_FORCEINLINE uintptr_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr) + template + BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr) { - typedef pointer_uintptr_caster caster_t; + typedef pointer_offset_caster caster_t; #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF //offset == 1 && ptr != 0 is not legal for this pointer if(!ptr){ return 1; } else{ - uintptr_t offset = caster_t(ptr).uintptr() - caster_t(this_ptr).uintptr(); + OffsetType offset = caster_t(ptr).offset()- caster_t(this_ptr).offset(); BOOST_ASSERT(offset != 1); return offset; } #else - //const uintptr_t other = -uintptr_t(ptr != 0); - //const uintptr_t offset = (caster_t(ptr).uintptr() - caster_t(this_ptr).uintptr()) & other; - //return offset + uintptr_t(!other); + //const OffsetType other = -OffsetType(ptr != 0); + //const OffsetType offset = (caster_t(ptr).offset() - caster_t(this_ptr).offset()) & other; + //return offset + OffsetType(!other); // - uintptr_t offset = caster_t(ptr).uintptr() - caster_t(this_ptr).uintptr(); + OffsetType offset = caster_t(ptr).offset() - caster_t(this_ptr).offset(); --offset; - uintptr_t mask = uintptr_t(ptr == 0); + OffsetType mask = ptr == 0; --mask; offset &= mask; return ++offset; @@ -140,28 +145,29 @@ namespace ipcdetail { // //////////////////////////////////////////////////////////////////////// #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER - BOOST_INTERPROCESS_FORCEINLINE uintptr_t offset_ptr_to_offset_from_other - (const volatile void *this_ptr, const volatile void *other_ptr, uintptr_t other_offset) + template + BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset_from_other + (const volatile void *this_ptr, const volatile void *other_ptr, OffsetType other_offset) { - typedef pointer_uintptr_caster caster_t; + typedef pointer_offset_caster caster_t; #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER if(other_offset == 1){ return 1; } else{ - uintptr_t offset = caster_t(other_ptr).uintptr() - caster_t(this_ptr).uintptr() + other_offset; + OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset() + other_offset; BOOST_ASSERT(offset != 1); return offset; } #else - uintptr_t mask = other_offset == 1; + OffsetType mask = other_offset == 1; --mask; - uintptr_t offset = caster_t(other_ptr).uintptr() - caster_t(this_ptr).uintptr(); + OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset(); offset &= mask; return offset + other_offset; - //uintptr_t mask = -uintptr_t(other_offset != 1); - //uintptr_t offset = caster_t(other_ptr).uintptr() - caster_t(this_ptr).uintptr(); + //OffsetType mask = -OffsetType(other_offset != 1); + //OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset(); //offset &= mask; //return offset + other_offset; #endif @@ -216,9 +222,9 @@ namespace ipcdetail { //! //!Note: offset_ptr uses implementation defined properties, present in most platforms, for //!performance reasons: -//! - Assumes that uintptr_t representation of nullptr is (uintptr_t)zero. -//! - Assumes that incrementing a uintptr_t obtained from a pointer is equivalent -//! to incrementing the pointer and then converting it back to uintptr_t. +//! - Assumes that OffsetType representation of nullptr is (OffsetType)zero. +//! - Assumes that incrementing a OffsetType obtained from a pointer is equivalent +//! to incrementing the pointer and then converting it back to OffsetType. template class offset_ptr { @@ -252,7 +258,7 @@ class offset_ptr //!Constructor from raw pointer (allows "0" pointer conversion). //!Never throws. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(pointer ptr) BOOST_NOEXCEPT - : internal(static_cast(ipcdetail::offset_ptr_to_offset(ptr, this))) + : internal(ipcdetail::offset_ptr_to_offset(ptr, this)) {} //!Constructor from other pointer. @@ -260,15 +266,13 @@ class offset_ptr template BOOST_INTERPROCESS_FORCEINLINE offset_ptr( T *ptr , typename ipcdetail::enable_if< ::boost::is_convertible >::type * = 0) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(static_cast(ptr), this))) + : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr), this)) {} //!Constructor from other offset_ptr //!Never throws. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr& ptr) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset))) + : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset)) {} //!Constructor from other offset_ptr. Only takes part in overload resolution @@ -279,8 +283,7 @@ class offset_ptr , typename ipcdetail::enable_if_convertible_equal_address::type* = 0 #endif ) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset()))) + : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset())) {} #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED @@ -288,8 +291,7 @@ class offset_ptr template BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr &ptr , typename ipcdetail::enable_if_convertible_unequal_address::type* = 0) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)) {} #endif @@ -304,46 +306,41 @@ class offset_ptr >::type * = 0 #endif ) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)) {} //!Emulates static_cast operator. //!Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::static_cast_tag) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(static_cast(r.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(static_cast(r.get()), this)) {} //!Emulates const_cast operator. //!Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::const_cast_tag) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(const_cast(r.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(const_cast(r.get()), this)) {} //!Emulates dynamic_cast operator. //!Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::dynamic_cast_tag) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(dynamic_cast(r.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(dynamic_cast(r.get()), this)) {} //!Emulates reinterpret_cast operator. //!Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::reinterpret_cast_tag) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(reinterpret_cast(r.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(reinterpret_cast(r.get()), this)) {} //!Obtains raw pointer from offset. //!Never throws. BOOST_INTERPROCESS_FORCEINLINE pointer get() const BOOST_NOEXCEPT - { return (pointer)ipcdetail::offset_ptr_to_raw_pointer(this, this->internal.m_offset); } + { return static_cast(ipcdetail::offset_ptr_to_raw_pointer(this, this->internal.m_offset)); } BOOST_INTERPROCESS_FORCEINLINE offset_type get_offset() const BOOST_NOEXCEPT { return this->internal.m_offset; } @@ -371,8 +368,7 @@ class offset_ptr //!Never throws. BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (pointer from) BOOST_NOEXCEPT { - this->internal.m_offset = - static_cast(ipcdetail::offset_ptr_to_offset(from, this)); + this->internal.m_offset = ipcdetail::offset_ptr_to_offset(from, this); return *this; } @@ -380,8 +376,7 @@ class offset_ptr //!Never throws. BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (const offset_ptr & ptr) BOOST_NOEXCEPT { - this->internal.m_offset = - static_cast(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset)); + this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset); return *this; } @@ -559,15 +554,13 @@ class offset_ptr template BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr &ptr, ipcdetail::bool_) BOOST_NOEXCEPT { //no need to pointer adjustment - this->internal.m_offset = - static_cast(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset())); + this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset()); } template BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr &ptr, ipcdetail::bool_) BOOST_NOEXCEPT { //we must convert to raw before calculating the offset - this->internal.m_offset = - static_cast(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)); + this->internal.m_offset = ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this); } #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) @@ -705,7 +698,7 @@ struct pointer_plus_bits, NumBits> typedef boost::interprocess::offset_ptr pointer; //Bits are stored in the lower bits of the pointer except the LSB, //because this bit is used to represent the null pointer. - static const uintptr_t Mask = ((uintptr_t(1) << uintptr_t(NumBits)) - uintptr_t(1)) << uintptr_t(1); + static const O Mask = ((static_cast(1) << NumBits) - static_cast(1)) << 1; BOOST_STATIC_ASSERT(0 ==(Mask&1)); //We must ALWAYS take argument "n" by reference as a copy of a null pointer @@ -714,7 +707,7 @@ struct pointer_plus_bits, NumBits> BOOST_INTERPROCESS_FORCEINLINE static pointer get_pointer(const pointer &n) BOOST_NOEXCEPT { pointer p; - O const tmp_off = n.priv_offset() & O(~Mask); + O const tmp_off = n.priv_offset() & ~Mask; p.priv_offset() = boost::interprocess::ipcdetail::offset_ptr_to_offset_from_other(&p, &n, tmp_off); return p; } @@ -722,7 +715,7 @@ struct pointer_plus_bits, NumBits> BOOST_INTERPROCESS_FORCEINLINE static void set_pointer(pointer &n, const pointer &p) BOOST_NOEXCEPT { BOOST_ASSERT(0 == (get_bits)(p)); - O const stored_bits = O(n.priv_offset() & Mask); + O const stored_bits = n.priv_offset() & Mask; n = p; n.priv_offset() |= stored_bits; } @@ -736,7 +729,7 @@ struct pointer_plus_bits, NumBits> { BOOST_ASSERT(b < (std::size_t(1) << NumBits)); O tmp = n.priv_offset(); - tmp &= O(~Mask); + tmp &= ~Mask; tmp |= O(b << 1u); n.priv_offset() = tmp; }