offset_ptr.hpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2015. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/interprocess for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP
  11. #define BOOST_INTERPROCESS_OFFSET_PTR_HPP
  12. #ifndef BOOST_CONFIG_HPP
  13. # include <boost/config.hpp>
  14. #endif
  15. #
  16. #if defined(BOOST_HAS_PRAGMA_ONCE)
  17. # pragma once
  18. #endif
  19. #include <boost/interprocess/detail/config_begin.hpp>
  20. #include <boost/interprocess/detail/workaround.hpp>
  21. #include <boost/move/detail/type_traits.hpp>
  22. #include <boost/interprocess/interprocess_fwd.hpp>
  23. #include <boost/interprocess/interprocess_printers.hpp>
  24. #include <boost/interprocess/detail/utilities.hpp>
  25. #include <boost/interprocess/detail/cast_tags.hpp>
  26. #include <boost/interprocess/detail/mpl.hpp>
  27. #include <boost/container/detail/type_traits.hpp> //alignment_of, aligned_storage
  28. #include <boost/assert.hpp>
  29. #include <iosfwd>
  30. #include <cstddef>
  31. #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
  32. #pragma GCC diagnostic push
  33. #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  34. #endif
  35. //!\file
  36. //!Describes a smart pointer that stores the offset between this pointer and
  37. //!target pointee, called offset_ptr.
  38. namespace boost {
  39. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  40. //Predeclarations
  41. template <class T>
  42. struct has_trivial_destructor;
  43. #endif //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  44. namespace interprocess {
  45. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  46. #if !defined( BOOST_NO_CXX11_NULLPTR )
  47. typedef decltype(nullptr) op_nullptr_t;
  48. #else
  49. struct op_nullptr_t
  50. {
  51. void* lx; //to achieve pointer alignment
  52. struct nat {int bool_conversion;};
  53. BOOST_INTERPROCESS_FORCEINLINE op_nullptr_t() {}
  54. BOOST_INTERPROCESS_FORCEINLINE op_nullptr_t(int nat::*) {}
  55. BOOST_INTERPROCESS_FORCEINLINE operator int nat::*() const { return 0; }
  56. template <class T>
  57. BOOST_INTERPROCESS_FORCEINLINE operator T*() const { return 0; }
  58. template <class T, class U>
  59. BOOST_INTERPROCESS_FORCEINLINE operator T U::* () const { return 0; }
  60. friend BOOST_INTERPROCESS_FORCEINLINE bool operator==(op_nullptr_t, op_nullptr_t) { return true; }
  61. friend BOOST_INTERPROCESS_FORCEINLINE bool operator!=(op_nullptr_t, op_nullptr_t) { return false; }
  62. };
  63. #endif
  64. namespace ipcdetail {
  65. //workarounds for void offset_ptrs
  66. struct op_nat{};
  67. template <class T> struct op_reference
  68. : add_reference<T>
  69. {};
  70. template <> struct op_reference<void>
  71. { typedef op_nat type; };
  72. template <> struct op_reference<void const>
  73. { typedef op_nat type; };
  74. template <> struct op_reference<void volatile>
  75. { typedef op_nat type; };
  76. template <> struct op_reference<void const volatile>
  77. { typedef op_nat type; };
  78. template<class OffsetType, std::size_t OffsetAlignment>
  79. union offset_ptr_internal
  80. {
  81. BOOST_INTERPROCESS_STATIC_ASSERT(sizeof(OffsetType) >= sizeof(uintptr_t));
  82. BOOST_INTERPROCESS_STATIC_ASSERT(boost::move_detail::is_integral<OffsetType>::value && boost::move_detail::is_unsigned<OffsetType>::value);
  83. BOOST_INTERPROCESS_FORCEINLINE explicit offset_ptr_internal(OffsetType off)
  84. : m_offset(off)
  85. {}
  86. OffsetType m_offset; //Distance between this object and pointee address
  87. typename ::boost::container::dtl::aligned_storage
  88. < sizeof(OffsetType)//for offset_type_alignment m_offset will be enough
  89. , (OffsetAlignment == offset_type_alignment) ? 1u : OffsetAlignment
  90. >::type alignment_helper;
  91. };
  92. //Note: using the address of a local variable to point to another address
  93. //is not standard conforming and this can be optimized-away by the compiler.
  94. //Non-inlining is a method to remain illegal but correct
  95. //Undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_XXX if your compiler can inline
  96. //this code without breaking the library
  97. ////////////////////////////////////////////////////////////////////////
  98. //
  99. // offset_ptr_to_raw_pointer
  100. //
  101. ////////////////////////////////////////////////////////////////////////
  102. #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
  103. template <class OffsetType>
  104. BOOST_INTERPROCESS_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, OffsetType offset)
  105. {
  106. typedef pointer_offset_caster<void*, OffsetType> caster_t;
  107. #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR
  108. if(offset == 1){
  109. return 0;
  110. }
  111. else{
  112. return caster_t(caster_t(this_ptr).offset() + offset).pointer();
  113. }
  114. #else
  115. OffsetType mask = offset == 1;
  116. --mask;
  117. OffsetType target_offset = caster_t(this_ptr).offset() + offset;
  118. target_offset &= mask;
  119. return caster_t(target_offset).pointer();
  120. #endif
  121. }
  122. ////////////////////////////////////////////////////////////////////////
  123. //
  124. // offset_ptr_to_offset
  125. //
  126. ////////////////////////////////////////////////////////////////////////
  127. #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
  128. template<class OffsetType>
  129. BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr)
  130. {
  131. typedef pointer_offset_caster<void*, OffsetType> caster_t;
  132. #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF
  133. //offset == 1 && ptr != 0 is not legal for this pointer
  134. if(!ptr){
  135. return 1;
  136. }
  137. else{
  138. OffsetType offset = caster_t(ptr).offset()- caster_t(this_ptr).offset();
  139. BOOST_ASSERT(offset != 1);
  140. return offset;
  141. }
  142. #else
  143. //const OffsetType other = -OffsetType(ptr != 0);
  144. //const OffsetType offset = (caster_t(ptr).offset() - caster_t(this_ptr).offset()) & other;
  145. //return offset + OffsetType(!other);
  146. //
  147. OffsetType offset = caster_t(ptr).offset() - caster_t(this_ptr).offset();
  148. --offset;
  149. OffsetType mask = ptr == 0;
  150. --mask;
  151. offset &= mask;
  152. return ++offset;
  153. #endif
  154. }
  155. ////////////////////////////////////////////////////////////////////////
  156. //
  157. // offset_ptr_to_offset_from_other
  158. //
  159. ////////////////////////////////////////////////////////////////////////
  160. #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
  161. template<class OffsetType>
  162. BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset_from_other
  163. (const volatile void *this_ptr, const volatile void *other_ptr, OffsetType other_offset)
  164. {
  165. typedef pointer_offset_caster<void*, OffsetType> caster_t;
  166. #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER
  167. if(other_offset == 1){
  168. return 1;
  169. }
  170. else{
  171. OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset() + other_offset;
  172. BOOST_ASSERT(offset != 1);
  173. return offset;
  174. }
  175. #else
  176. OffsetType mask = other_offset == 1;
  177. --mask;
  178. OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset();
  179. offset &= mask;
  180. return offset + other_offset;
  181. //OffsetType mask = -OffsetType(other_offset != 1);
  182. //OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset();
  183. //offset &= mask;
  184. //return offset + other_offset;
  185. #endif
  186. }
  187. ////////////////////////////////////////////////////////////////////////
  188. //
  189. // Let's assume cast to void and cv cast don't change any target address
  190. //
  191. ////////////////////////////////////////////////////////////////////////
  192. template<class From, class To>
  193. struct offset_ptr_maintains_address
  194. {
  195. static const bool value = ipcdetail::is_cv_same<From, To>::value
  196. || ipcdetail::is_cv_same<void, To>::value
  197. || ipcdetail::is_cv_same<char, To>::value
  198. ;
  199. };
  200. template<class From, class To, class Ret = void>
  201. struct enable_if_convertible_equal_address
  202. : enable_if_c< ::boost::move_detail::is_convertible<From*, To*>::value
  203. && offset_ptr_maintains_address<From, To>::value
  204. , Ret>
  205. {};
  206. template<class From, class To, class Ret = void>
  207. struct enable_if_convertible_unequal_address
  208. : enable_if_c< ::boost::move_detail::is_convertible<From*, To*>::value
  209. && !offset_ptr_maintains_address<From, To>::value
  210. , Ret>
  211. {};
  212. } //namespace ipcdetail {
  213. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  214. //!A smart pointer that stores the offset between the pointer and the
  215. //!object it points to. This allows special properties, since
  216. //!the pointer is independent from the address of the pointee, if the
  217. //!pointer and the pointee are still separated by the same offset. This feature
  218. //!converts offset_ptr in a smart pointer that can be placed in shared memory and
  219. //!memory mapped files mapped at different addresses in every process.
  220. //!
  221. //! \tparam PointedType The type of the pointee.
  222. //! \tparam DifferenceType A signed integer type that can represent the arithmetic operations on the pointer
  223. //! \tparam OffsetType An unsigned integer type that can represent the
  224. //! distance between two pointers reinterpret_cast-ed as unsigned integers. This type
  225. //! should be at least of the same size of std::uintptr_t. In some systems it's possible to communicate
  226. //! between 32 and 64 bit processes using 64 bit offsets.
  227. //! \tparam OffsetAlignment Alignment of the OffsetType stored inside. In some systems might be necessary
  228. //! to align it to 64 bits in order to communicate 32 and 64 bit processes using 64 bit offsets.
  229. //!
  230. //!<b>Note</b>: offset_ptr uses implementation defined properties, present in most platforms, for
  231. //!performance reasons:
  232. //! - Assumes that OffsetType representation of nullptr is (OffsetType)zero.
  233. //! - Assumes that incrementing a OffsetType obtained from a pointer is equivalent
  234. //! to incrementing the pointer and then converting it back to OffsetType.
  235. template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
  236. class offset_ptr
  237. {
  238. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  239. typedef offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> self_t;
  240. void unspecified_bool_type_func() const {}
  241. typedef void (self_t::*unspecified_bool_type)() const;
  242. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  243. public:
  244. typedef PointedType element_type;
  245. typedef PointedType * pointer;
  246. typedef typename ipcdetail::
  247. op_reference<PointedType>::type reference;
  248. typedef typename ipcdetail::
  249. remove_volatile<typename ipcdetail::
  250. remove_const<PointedType>::type
  251. >::type value_type;
  252. typedef DifferenceType difference_type;
  253. typedef std::random_access_iterator_tag iterator_category;
  254. typedef OffsetType offset_type;
  255. public: //Public Functions
  256. //!Default constructor (null pointer).
  257. //!Never throws.
  258. BOOST_INTERPROCESS_FORCEINLINE offset_ptr() BOOST_NOEXCEPT
  259. : internal(1)
  260. {}
  261. //!Constructor from nullptr.
  262. //!Never throws.
  263. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(op_nullptr_t) BOOST_NOEXCEPT
  264. : internal(1)
  265. {}
  266. #if defined( BOOST_NO_CXX11_NULLPTR )
  267. //!Constructor from nullptr. Some compilers (e.g. g++14) in C++03 mode have problems with op_nullptr_t
  268. //!so a helper overload is needed. Never throws.
  269. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(int ipcdetail::op_nat::*) BOOST_NOEXCEPT
  270. : internal(1)
  271. {}
  272. #endif //BOOST_NO_CXX11_NULLPTR
  273. //!Constructor from raw pointer. Only takes part in overload resolution if T* is convertible to PointedType*
  274. //!Never throws.
  275. template <class T>
  276. BOOST_INTERPROCESS_FORCEINLINE offset_ptr( T *ptr
  277. #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  278. , typename ipcdetail::enable_if< ::boost::move_detail::is_convertible<T*, PointedType*> >::type * = 0
  279. #endif
  280. ) BOOST_NOEXCEPT
  281. : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(static_cast<PointedType*>(ptr), this))
  282. {}
  283. //!Constructor from other offset_ptr.
  284. //!Never throws.
  285. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr& ptr) BOOST_NOEXCEPT
  286. : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset))
  287. {}
  288. //!Constructor from other offset_ptr. Only takes part in overload resolution
  289. //!if T2* is convertible to PointedType*. Never throws.
  290. template<class T2>
  291. BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
  292. #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  293. , typename ipcdetail::enable_if_convertible_equal_address<T2, PointedType>::type* = 0
  294. #endif
  295. ) BOOST_NOEXCEPT
  296. : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset()))
  297. {}
  298. #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  299. template<class T2>
  300. BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr
  301. , typename ipcdetail::enable_if_convertible_unequal_address<T2, PointedType>::type* = 0) BOOST_NOEXCEPT
  302. : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(static_cast<PointedType*>(ptr.get()), this))
  303. {}
  304. #endif
  305. //!Emulates static_cast operator.
  306. //!Never throws.
  307. template<class T2, class P2, class O2, std::size_t A2>
  308. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::static_cast_tag) BOOST_NOEXCEPT
  309. : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(static_cast<PointedType*>(r.get()), this))
  310. {}
  311. //!Emulates const_cast operator.
  312. //!Never throws.
  313. template<class T2, class P2, class O2, std::size_t A2>
  314. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::const_cast_tag) BOOST_NOEXCEPT
  315. : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(const_cast<PointedType*>(r.get()), this))
  316. {}
  317. //!Emulates dynamic_cast operator.
  318. //!Never throws.
  319. template<class T2, class P2, class O2, std::size_t A2>
  320. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::dynamic_cast_tag) BOOST_NOEXCEPT
  321. : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(dynamic_cast<PointedType*>(r.get()), this))
  322. {}
  323. //!Emulates reinterpret_cast operator.
  324. //!Never throws.
  325. template<class T2, class P2, class O2, std::size_t A2>
  326. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr<T2, P2, O2, A2> & r, ipcdetail::reinterpret_cast_tag) BOOST_NOEXCEPT
  327. : internal(ipcdetail::offset_ptr_to_offset<OffsetType>(reinterpret_cast<PointedType*>(r.get()), this))
  328. {}
  329. //!Obtains raw pointer from offset.
  330. //!Never throws.
  331. BOOST_INTERPROCESS_FORCEINLINE pointer get() const BOOST_NOEXCEPT
  332. { return static_cast<pointer>(ipcdetail::offset_ptr_to_raw_pointer(this, this->internal.m_offset)); }
  333. BOOST_INTERPROCESS_FORCEINLINE offset_type get_offset() const BOOST_NOEXCEPT
  334. { return this->internal.m_offset; }
  335. //!Pointer-like -> operator. It can return 0 pointer.
  336. //!Never throws.
  337. BOOST_INTERPROCESS_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
  338. { return this->get(); }
  339. //!Dereferencing operator, if it is a null offset_ptr behavior
  340. //! is undefined. Never throws.
  341. BOOST_INTERPROCESS_FORCEINLINE reference operator*() const BOOST_NOEXCEPT
  342. {
  343. pointer p = this->get();
  344. reference r = *p;
  345. return r;
  346. }
  347. //!Indexing operator.
  348. //!Never throws.
  349. BOOST_INTERPROCESS_FORCEINLINE reference operator[](difference_type idx) const BOOST_NOEXCEPT
  350. { return this->get()[idx]; }
  351. //!Assignment from raw pointer. Only takes part in overload resolution if T* is convertible to PointedType*
  352. //!Never throws.
  353. template<class T> BOOST_INTERPROCESS_FORCEINLINE
  354. #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  355. typename ipcdetail::enable_if_c
  356. < ::boost::move_detail::is_convertible<T*, PointedType*>::value, offset_ptr&>::type
  357. #else
  358. offset_ptr&
  359. #endif
  360. operator= (T *ptr) BOOST_NOEXCEPT
  361. {
  362. this->internal.m_offset = ipcdetail::offset_ptr_to_offset<OffsetType>(static_cast<PointedType*>(ptr), this);
  363. return *this;
  364. }
  365. //!Assignment from other offset_ptr.
  366. //!Never throws.
  367. BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (const offset_ptr & ptr) BOOST_NOEXCEPT
  368. {
  369. this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset);
  370. return *this;
  371. }
  372. //!Assignment from nullptr.
  373. //!Never throws.
  374. BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (op_nullptr_t) BOOST_NOEXCEPT
  375. {
  376. this->internal.m_offset = 1;
  377. return *this;
  378. }
  379. #if defined( BOOST_NO_CXX11_NULLPTR )
  380. //!Assignment from nullptr. Some compilers (e.g. g++14) in C++03 mode have problems with op_nullptr_t
  381. //!so a helper overload is needed. Never throws.
  382. BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (int ipcdetail::op_nat::*) BOOST_NOEXCEPT
  383. {
  384. this->internal.m_offset = 1;
  385. return *this;
  386. }
  387. #endif //BOOST_NO_CXX11_NULLPTR
  388. //!Assignment from related offset_ptr.
  389. //!Only takes part in overload resolution if T2* is convertible to PointedType*
  390. //!Never throws.
  391. template<class T2> BOOST_INTERPROCESS_FORCEINLINE
  392. #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  393. typename ipcdetail::enable_if_c
  394. < ::boost::move_detail::is_convertible<T2*, PointedType*>::value, offset_ptr&>::type
  395. #else
  396. offset_ptr&
  397. #endif
  398. operator= (const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr) BOOST_NOEXCEPT
  399. {
  400. this->assign(ptr, ipcdetail::bool_<ipcdetail::offset_ptr_maintains_address<T2, PointedType>::value>());
  401. return *this;
  402. }
  403. public:
  404. //!offset_ptr += difference_type.
  405. //!Never throws.
  406. BOOST_INTERPROCESS_FORCEINLINE offset_ptr &operator+= (difference_type offset) BOOST_NOEXCEPT
  407. { this->inc_offset(offset * difference_type(sizeof(PointedType))); return *this; }
  408. //!offset_ptr -= difference_type.
  409. //!Never throws.
  410. BOOST_INTERPROCESS_FORCEINLINE offset_ptr &operator-= (difference_type offset) BOOST_NOEXCEPT
  411. { this->dec_offset(offset * difference_type(sizeof(PointedType))); return *this; }
  412. //!++offset_ptr.
  413. //!Never throws.
  414. BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator++ (void) BOOST_NOEXCEPT
  415. { this->inc_offset(difference_type(sizeof(PointedType))); return *this; }
  416. //!offset_ptr++.
  417. //!Never throws.
  418. BOOST_INTERPROCESS_FORCEINLINE offset_ptr operator++ (int) BOOST_NOEXCEPT
  419. {
  420. offset_ptr tmp(*this);
  421. this->inc_offset(sizeof (PointedType));
  422. return tmp;
  423. }
  424. //!--offset_ptr.
  425. //!Never throws.
  426. BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator-- (void) BOOST_NOEXCEPT
  427. { this->dec_offset(sizeof (PointedType)); return *this; }
  428. //!offset_ptr--.
  429. //!Never throws.
  430. BOOST_INTERPROCESS_FORCEINLINE offset_ptr operator-- (int) BOOST_NOEXCEPT
  431. {
  432. offset_ptr tmp(*this);
  433. this->dec_offset(sizeof (PointedType));
  434. return tmp;
  435. }
  436. //!safe bool conversion operator.
  437. //!Never throws.
  438. #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
  439. BOOST_INTERPROCESS_FORCEINLINE operator unspecified_bool_type() const BOOST_NOEXCEPT
  440. { return this->internal.m_offset != 1? &self_t::unspecified_bool_type_func : 0; }
  441. #else
  442. explicit operator bool() const BOOST_NOEXCEPT
  443. { return this->internal.m_offset != 1; }
  444. #endif
  445. //!Not operator. Not needed in theory, but improves portability.
  446. //!Never throws
  447. BOOST_INTERPROCESS_FORCEINLINE bool operator! () const BOOST_NOEXCEPT
  448. { return this->internal.m_offset == 1; }
  449. //!Compatibility with pointer_traits
  450. //!
  451. #if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  452. template <class U>
  453. struct rebind
  454. { typedef offset_ptr<U, DifferenceType, OffsetType, OffsetAlignment> other; };
  455. #else
  456. template <class U>
  457. using rebind = offset_ptr<U, DifferenceType, OffsetType, OffsetAlignment>;
  458. #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  459. typedef offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> other;
  460. #endif //BOOST_INTERPROCESS_DOXYGEN_INVOKED
  461. #endif
  462. //!Compatibility with pointer_traits
  463. //!
  464. BOOST_INTERPROCESS_FORCEINLINE static offset_ptr pointer_to(typename ipcdetail::op_reference<PointedType>::type r) BOOST_NOEXCEPT
  465. { return offset_ptr(&r); }
  466. //!difference_type + offset_ptr
  467. //!operation
  468. BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator+(difference_type diff, offset_ptr right) BOOST_NOEXCEPT
  469. { right += diff; return right; }
  470. //!offset_ptr + difference_type
  471. //!operation
  472. BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator+(offset_ptr left, difference_type diff) BOOST_NOEXCEPT
  473. { left += diff; return left; }
  474. //!offset_ptr - diff
  475. //!operation
  476. BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator-(offset_ptr left, difference_type diff) BOOST_NOEXCEPT
  477. { left -= diff; return left; }
  478. //!offset_ptr - diff
  479. //!operation
  480. BOOST_INTERPROCESS_FORCEINLINE friend offset_ptr operator-(difference_type diff, offset_ptr right) BOOST_NOEXCEPT
  481. { right -= diff; return right; }
  482. //!offset_ptr - offset_ptr
  483. //!operation
  484. BOOST_INTERPROCESS_FORCEINLINE friend difference_type operator-(const offset_ptr &pt, const offset_ptr &pt2) BOOST_NOEXCEPT
  485. { return difference_type(pt.get()- pt2.get()); }
  486. //Comparison
  487. BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  488. { return pt1.get() == pt2.get(); }
  489. BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  490. { return pt1.get() != pt2.get(); }
  491. BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  492. { return pt1.get() < pt2.get(); }
  493. BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  494. { return pt1.get() <= pt2.get(); }
  495. BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  496. { return pt1.get() > pt2.get(); }
  497. BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(const offset_ptr &pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  498. { return pt1.get() >= pt2.get(); }
  499. //Comparison to raw ptr to support literal 0
  500. BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  501. { return pt1 == pt2.get(); }
  502. BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  503. { return pt1 != pt2.get(); }
  504. BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  505. { return pt1 < pt2.get(); }
  506. BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  507. { return pt1 <= pt2.get(); }
  508. BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  509. { return pt1 > pt2.get(); }
  510. BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(pointer pt1, const offset_ptr &pt2) BOOST_NOEXCEPT
  511. { return pt1 >= pt2.get(); }
  512. //Comparison
  513. BOOST_INTERPROCESS_FORCEINLINE friend bool operator== (const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
  514. { return pt1.get() == pt2; }
  515. BOOST_INTERPROCESS_FORCEINLINE friend bool operator!= (const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
  516. { return pt1.get() != pt2; }
  517. BOOST_INTERPROCESS_FORCEINLINE friend bool operator<(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
  518. { return pt1.get() < pt2; }
  519. BOOST_INTERPROCESS_FORCEINLINE friend bool operator<=(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
  520. { return pt1.get() <= pt2; }
  521. BOOST_INTERPROCESS_FORCEINLINE friend bool operator>(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
  522. { return pt1.get() > pt2; }
  523. BOOST_INTERPROCESS_FORCEINLINE friend bool operator>=(const offset_ptr &pt1, pointer pt2) BOOST_NOEXCEPT
  524. { return pt1.get() >= pt2; }
  525. BOOST_INTERPROCESS_FORCEINLINE friend void swap(offset_ptr &left, offset_ptr &right) BOOST_NOEXCEPT
  526. {
  527. pointer ptr = right.get();
  528. right = left;
  529. left = ptr;
  530. }
  531. private:
  532. template<class T2>
  533. BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr, ipcdetail::bool_<true>) BOOST_NOEXCEPT
  534. { //no need to pointer adjustment
  535. this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other<OffsetType>(this, &ptr, ptr.get_offset());
  536. }
  537. template<class T2>
  538. BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr<T2, DifferenceType, OffsetType, OffsetAlignment> &ptr, ipcdetail::bool_<false>) BOOST_NOEXCEPT
  539. { //we must convert to raw before calculating the offset
  540. this->internal.m_offset = ipcdetail::offset_ptr_to_offset<OffsetType>(static_cast<PointedType*>(ptr.get()), this);
  541. }
  542. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  543. BOOST_INTERPROCESS_FORCEINLINE void inc_offset(DifferenceType bytes) BOOST_NOEXCEPT
  544. { internal.m_offset += OffsetType(bytes); }
  545. BOOST_INTERPROCESS_FORCEINLINE void dec_offset(DifferenceType bytes) BOOST_NOEXCEPT
  546. { internal.m_offset -= OffsetType(bytes); }
  547. ipcdetail::offset_ptr_internal<OffsetType, OffsetAlignment> internal;
  548. public:
  549. BOOST_INTERPROCESS_FORCEINLINE const OffsetType &priv_offset() const BOOST_NOEXCEPT
  550. { return internal.m_offset; }
  551. BOOST_INTERPROCESS_FORCEINLINE OffsetType &priv_offset() BOOST_NOEXCEPT
  552. { return internal.m_offset; }
  553. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  554. };
  555. //!operator<<
  556. //!for offset ptr
  557. template<class E, class T, class W, class X, class Y, std::size_t Z>
  558. inline std::basic_ostream<E, T> & operator<<
  559. (std::basic_ostream<E, T> & os, offset_ptr<W, X, Y, Z> const & p)
  560. { return os << p.get_offset(); }
  561. //!operator>>
  562. //!for offset ptr
  563. template<class E, class T, class W, class X, class Y, std::size_t Z>
  564. inline std::basic_istream<E, T> & operator>>
  565. (std::basic_istream<E, T> & is, offset_ptr<W, X, Y, Z> & p)
  566. { return is >> p.get_offset(); }
  567. //!Simulation of static_cast between pointers. Never throws.
  568. template<class T1, class P, class O, std::size_t A, class T2>
  569. BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr<T1, P, O, A>
  570. static_pointer_cast(const boost::interprocess::offset_ptr<T2, P, O, A> & r) BOOST_NOEXCEPT
  571. {
  572. return boost::interprocess::offset_ptr<T1, P, O, A>
  573. (r, boost::interprocess::ipcdetail::static_cast_tag());
  574. }
  575. //!Simulation of const_cast between pointers. Never throws.
  576. template<class T1, class P, class O, std::size_t A, class T2>
  577. BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr<T1, P, O, A>
  578. const_pointer_cast(const boost::interprocess::offset_ptr<T2, P, O, A> & r) BOOST_NOEXCEPT
  579. {
  580. return boost::interprocess::offset_ptr<T1, P, O, A>
  581. (r, boost::interprocess::ipcdetail::const_cast_tag());
  582. }
  583. //!Simulation of dynamic_cast between pointers. Never throws.
  584. template<class T1, class P, class O, std::size_t A, class T2>
  585. BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr<T1, P, O, A>
  586. dynamic_pointer_cast(const boost::interprocess::offset_ptr<T2, P, O, A> & r) BOOST_NOEXCEPT
  587. {
  588. return boost::interprocess::offset_ptr<T1, P, O, A>
  589. (r, boost::interprocess::ipcdetail::dynamic_cast_tag());
  590. }
  591. //!Simulation of reinterpret_cast between pointers. Never throws.
  592. template<class T1, class P, class O, std::size_t A, class T2>
  593. BOOST_INTERPROCESS_FORCEINLINE boost::interprocess::offset_ptr<T1, P, O, A>
  594. reinterpret_pointer_cast(const boost::interprocess::offset_ptr<T2, P, O, A> & r) BOOST_NOEXCEPT
  595. {
  596. return boost::interprocess::offset_ptr<T1, P, O, A>
  597. (r, boost::interprocess::ipcdetail::reinterpret_cast_tag());
  598. }
  599. } //namespace interprocess {
  600. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  601. ///has_trivial_destructor<> == true_type specialization for optimizations
  602. template <class T, class P, class O, std::size_t A>
  603. struct has_trivial_destructor< ::boost::interprocess::offset_ptr<T, P, O, A> >
  604. {
  605. static const bool value = true;
  606. };
  607. namespace move_detail {
  608. ///has_trivial_destructor<> == true_type specialization for optimizations
  609. template <class T, class P, class O, std::size_t A>
  610. struct is_trivially_destructible< ::boost::interprocess::offset_ptr<T, P, O, A> >
  611. {
  612. static const bool value = true;
  613. };
  614. } //namespace move_detail {
  615. namespace interprocess {
  616. //!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr.
  617. //!Never throws.
  618. template <class T, class P, class O, std::size_t A>
  619. BOOST_INTERPROCESS_FORCEINLINE T * to_raw_pointer(boost::interprocess::offset_ptr<T, P, O, A> const & p) BOOST_NOEXCEPT
  620. { return ipcdetail::to_raw_pointer(p); }
  621. } //namespace interprocess
  622. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  623. } //namespace boost {
  624. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  625. namespace boost{
  626. //This is to support embedding a bit in the pointer
  627. //for intrusive containers, saving space
  628. namespace intrusive {
  629. //Predeclaration to avoid including header
  630. template<class VoidPointer, std::size_t N>
  631. struct max_pointer_plus_bits;
  632. template<std::size_t OffsetAlignment, class P, class O, std::size_t A>
  633. struct max_pointer_plus_bits<boost::interprocess::offset_ptr<void, P, O, A>, OffsetAlignment>
  634. {
  635. //The offset ptr can embed one bit less than the alignment since it
  636. //uses offset == 1 to store the null pointer.
  637. static const std::size_t value = ::boost::interprocess::ipcdetail::ls_zeros<OffsetAlignment>::value - 1;
  638. };
  639. //Predeclaration
  640. template<class Pointer, std::size_t NumBits>
  641. struct pointer_plus_bits;
  642. template<class T, class P, class O, std::size_t A, std::size_t NumBits>
  643. struct pointer_plus_bits<boost::interprocess::offset_ptr<T, P, O, A>, NumBits>
  644. {
  645. typedef boost::interprocess::offset_ptr<T, P, O, A> pointer;
  646. //Bits are stored in the lower bits of the pointer except the LSB,
  647. //because this bit is used to represent the null pointer.
  648. static const O Mask = ((static_cast<O>(1) << NumBits) - static_cast<O>(1)) << 1;
  649. BOOST_INTERPROCESS_STATIC_ASSERT(0 ==(Mask&1));
  650. //We must ALWAYS take argument "n" by reference as a copy of a null pointer
  651. //with a bit (e.g. offset == 3) would be incorrectly copied and interpreted as non-null.
  652. BOOST_INTERPROCESS_FORCEINLINE static pointer get_pointer(const pointer &n) BOOST_NOEXCEPT
  653. {
  654. pointer p;
  655. O const tmp_off = n.priv_offset() & ~Mask;
  656. p.priv_offset() = boost::interprocess::ipcdetail::offset_ptr_to_offset_from_other(&p, &n, tmp_off);
  657. return p;
  658. }
  659. BOOST_INTERPROCESS_FORCEINLINE static void set_pointer(pointer &n, const pointer &p) BOOST_NOEXCEPT
  660. {
  661. BOOST_ASSERT(0 == (get_bits)(p));
  662. O const stored_bits = n.priv_offset() & Mask;
  663. n = p;
  664. n.priv_offset() |= stored_bits;
  665. }
  666. BOOST_INTERPROCESS_FORCEINLINE static std::size_t get_bits(const pointer &n) BOOST_NOEXCEPT
  667. {
  668. return std::size_t((n.priv_offset() & Mask) >> 1u);
  669. }
  670. BOOST_INTERPROCESS_FORCEINLINE static void set_bits(pointer &n, std::size_t const b) BOOST_NOEXCEPT
  671. {
  672. BOOST_ASSERT(b < (std::size_t(1) << NumBits));
  673. O tmp = n.priv_offset();
  674. tmp &= ~Mask;
  675. tmp |= O(b << 1u);
  676. n.priv_offset() = tmp;
  677. }
  678. };
  679. } //namespace intrusive
  680. //Predeclaration
  681. template<class T, class U>
  682. struct pointer_to_other;
  683. //Backwards compatibility with pointer_to_other
  684. template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment, class U>
  685. struct pointer_to_other
  686. < ::boost::interprocess::offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment>, U >
  687. {
  688. typedef ::boost::interprocess::offset_ptr<U, DifferenceType, OffsetType, OffsetAlignment> type;
  689. };
  690. } //namespace boost{
  691. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  692. #include <boost/interprocess/detail/config_end.hpp>
  693. #if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
  694. #pragma GCC diagnostic pop
  695. #endif
  696. #endif //#ifndef BOOST_INTERPROCESS_OFFSET_PTR_HPP