offset_ptr.hpp 31 KB

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