offset_ptr.hpp 26 KB

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