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