offset_ptr.hpp 26 KB

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