1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2005-2008. 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)
7 // See http://www.boost.org/libs/interprocess for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 #ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP
12 #define BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP
14 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/interprocess/detail/config_begin.hpp>
19 #include <boost/interprocess/detail/workaround.hpp>
21 #include <boost/interprocess/interprocess_fwd.hpp>
22 #include <boost/interprocess/detail/utilities.hpp>
23 #include <boost/interprocess/detail/math_functions.hpp>
24 #include <boost/interprocess/detail/cast_tags.hpp>
25 #include <boost/assert.hpp>
26 #include <boost/interprocess/sync/scoped_lock.hpp>
27 #include <boost/interprocess/sync/interprocess_mutex.hpp>
28 #include <boost/interprocess/containers/flat_map.hpp>
29 #include <boost/interprocess/containers/vector.hpp> //vector
30 #include <boost/interprocess/containers/set.hpp> //set
31 #include <boost/detail/no_exceptions_support.hpp>
32 #include <boost/interprocess/detail/mpl.hpp>
35 #include <boost/static_assert.hpp> //BOOST_STATIC_ASSERT
36 #include <climits> //CHAR_BIT
37 #include <boost/integer/static_log2.hpp>
38 #include <cassert> //assert
39 #include <boost/interprocess/detail/multi_segment_services.hpp>
47 struct has_trivial_constructor
;
50 struct has_trivial_destructor
;
52 namespace interprocess
{
55 struct is_multisegment_ptr
;
57 struct intersegment_base
59 typedef intersegment_base self_t
;
60 BOOST_STATIC_ASSERT((sizeof(std::size_t) == sizeof(void*)));
61 BOOST_STATIC_ASSERT((sizeof(void*)*CHAR_BIT
== 32 || sizeof(void*)*CHAR_BIT
== 64));
62 static const std::size_t size_t_bits
= (sizeof(void*)*CHAR_BIT
== 32) ? 32 : 64;
63 static const std::size_t ctrl_bits
= 2;
64 static const std::size_t align_bits
= 12;
65 static const std::size_t align
= std::size_t(1) << align_bits
;
66 static const std::size_t max_segment_size_bits
= size_t_bits
- 2;
67 static const std::size_t max_segment_size
= std::size_t(1) << max_segment_size_bits
;
69 static const std::size_t begin_bits
= max_segment_size_bits
- align_bits
;
70 static const std::size_t pow_size_bits_helper
= static_log2
<max_segment_size_bits
>::value
;
71 static const std::size_t pow_size_bits
=
72 (max_segment_size_bits
== (std::size_t(1) << pow_size_bits_helper
)) ?
73 pow_size_bits_helper
: pow_size_bits_helper
+ 1;
74 static const std::size_t frc_size_bits
=
75 size_t_bits
- ctrl_bits
- begin_bits
- pow_size_bits
;
77 BOOST_STATIC_ASSERT(((size_t_bits
- pow_size_bits
- frc_size_bits
) >= ctrl_bits
));
79 static const std::size_t relative_size_bits
=
80 size_t_bits
- max_segment_size_bits
- ctrl_bits
;
82 static const std::size_t is_pointee_outside
= 0;
83 static const std::size_t is_in_stack
= 1;
84 static const std::size_t is_relative
= 2;
85 static const std::size_t is_segmented
= 3;
86 static const std::size_t is_max_mode
= 4;
90 this->set_mode(is_pointee_outside
);
94 struct relative_addressing
97 std::size_t pow
: pow_size_bits
;
98 std::size_t frc
: frc_size_bits
;
99 std::size_t beg
: begin_bits
;
100 std::ptrdiff_t off
: sizeof(ptrdiff_t)*CHAR_BIT
- 2;
101 std::ptrdiff_t bits
: 2;
104 struct direct_addressing
106 std::size_t ctrl
: 2;
107 std::size_t dummy
: sizeof(std::size_t)*CHAR_BIT
- 2;
111 struct segmented_addressing
113 std::size_t ctrl
: 2;
114 std::size_t segment
: sizeof(std::size_t)*CHAR_BIT
- 2;
115 std::size_t off
: sizeof(std::size_t)*CHAR_BIT
- 2;
116 std::size_t bits
: 2;
120 relative_addressing relative
;
121 direct_addressing direct
;
122 segmented_addressing segmented
;
125 BOOST_STATIC_ASSERT(sizeof(members_t
) == 2*sizeof(std::size_t));
127 void *relative_calculate_begin_addr() const
129 const std::size_t mask
= ~(align
- 1);
130 std::size_t beg
= this->members
.relative
.beg
;
131 return reinterpret_cast<void*>((((std::size_t)this) & mask
) - (beg
<< align_bits
));
134 void relative_set_begin_from_base(void *addr
)
136 assert(addr
< static_cast<void*>(this));
137 std::size_t off
= reinterpret_cast<char*>(this) - reinterpret_cast<char*>(addr
);
138 members
.relative
.beg
= off
>> align_bits
;
141 //!Obtains the address pointed by the
143 std::size_t relative_size() const
145 std::size_t pow
= members
.relative
.pow
;
146 std::size_t size
= (std::size_t(1u) << pow
);
147 assert(pow
>= frc_size_bits
);
148 size
|= members
.relative
.frc
<< (pow
- frc_size_bits
);
152 static std::size_t calculate_size(std::size_t orig_size
, std::size_t &pow
, std::size_t &frc
)
154 if(orig_size
< align
)
156 orig_size
= detail::get_rounded_size_po2(orig_size
, align
);
157 pow
= detail::floor_log2(orig_size
);
158 std::size_t low_size
= (std::size_t(1) << pow
);
159 std::size_t diff
= orig_size
- low_size
;
160 assert(pow
>= frc_size_bits
);
161 std::size_t rounded
= detail::get_rounded_size_po2
162 (diff
, (1u << (pow
- frc_size_bits
)));
163 if(rounded
== low_size
){
169 frc
= rounded
>> (pow
- frc_size_bits
);
171 assert(((frc
<< (pow
- frc_size_bits
)) & (align
-1))==0);
172 return low_size
+ rounded
;
175 std::size_t get_mode()const
176 { return members
.direct
.ctrl
; }
178 void set_mode(std::size_t mode
)
180 assert(mode
< is_max_mode
);
181 members
.direct
.ctrl
= mode
;
184 //!Returns true if object represents
188 return (this->get_mode() < is_relative
) &&
189 !members
.direct
.dummy
&&
190 !members
.direct
.addr
;
193 //!Sets the object to represent
197 if(this->get_mode() >= is_relative
){
198 this->set_mode(is_pointee_outside
);
200 members
.direct
.dummy
= 0;
201 members
.direct
.addr
= 0;
204 static std::size_t round_size(std::size_t orig_size
)
206 std::size_t pow
, frc
;
207 return calculate_size(orig_size
, pow
, frc
);
213 //!Configures intersegment_ptr with the capability to address:
214 //!2^(sizeof(std::size_t)*CHAR_BIT/2) segment groups
215 //!2^(sizeof(std::size_t)*CHAR_BIT/2) segments per group.
216 //!2^(sizeof(std::size_t)*CHAR_BIT/2)-1 bytes maximum per segment.
217 //!The mapping is implemented through flat_maps synchronized with mutexes.
218 template <class Mutex
>
219 struct flat_map_intersegment
220 : public intersegment_base
222 typedef flat_map_intersegment
<Mutex
> self_t
;
224 void set_from_pointer(const volatile void *ptr
)
225 { this->set_from_pointer(const_cast<const void *>(ptr
)); }
227 //!Obtains the address pointed
229 void *get_pointer() const
234 switch(this->get_mode()){
236 return const_cast<char*>(reinterpret_cast<const char*>(this)) + members
.relative
.off
;
240 segment_info_t segment_info
;
243 get_segment_info_and_offset(this, segment_info
, offset
, this_base
);
244 char *base
= static_cast<char*>(segment_info
.group
->address_of(this->members
.segmented
.segment
));
245 return base
+ this->members
.segmented
.off
;
249 case is_pointee_outside
:
250 return members
.direct
.addr
;
258 //!Calculates the distance between two basic_intersegment_ptr-s.
259 //!This only works with two basic_intersegment_ptr pointing
260 //!to the same segment. Otherwise undefined
261 std::ptrdiff_t diff(const self_t
&other
) const
262 { return static_cast<char*>(this->get_pointer()) - static_cast<char*>(other
.get_pointer()); }
264 //!Returns true if both point to
266 bool equal(const self_t
&y
) const
267 { return this->get_pointer() == y
.get_pointer(); }
269 //!Returns true if *this is less than other.
270 //!This only works with two basic_intersegment_ptr pointing
271 //!to the same segment group. Otherwise undefined. Never throws
272 bool less(const self_t
&y
) const
273 { return this->get_pointer() < y
.get_pointer(); }
275 void swap(self_t
&other
)
277 void *ptr_this
= this->get_pointer();
278 void *ptr_other
= other
.get_pointer();
279 other
.set_from_pointer(ptr_this
);
280 this->set_from_pointer(ptr_other
);
283 //!Sets the object internals to represent the
284 //!address pointed by ptr
285 void set_from_pointer(const void *ptr
)
292 std::size_t mode
= this->get_mode();
293 if(mode
== is_in_stack
){
294 members
.direct
.addr
= const_cast<void*>(ptr
);
297 if(mode
== is_relative
){
298 char *beg_addr
= static_cast<char*>(this->relative_calculate_begin_addr());
299 std::size_t seg_size
= this->relative_size();
300 if(ptr
>= beg_addr
&& ptr
< (beg_addr
+ seg_size
)){
301 members
.relative
.off
= static_cast<const char*>(ptr
) - reinterpret_cast<const char*>(this);
305 std::size_t ptr_offset
;
306 std::size_t this_offset
;
307 segment_info_t ptr_info
;
308 segment_info_t this_info
;
311 get_segment_info_and_offset(this, this_info
, this_offset
, this_base
);
313 if(!this_info
.group
){
314 this->set_mode(is_in_stack
);
315 this->members
.direct
.addr
= const_cast<void*>(ptr
);
318 get_segment_info_and_offset(ptr
, ptr_info
, ptr_offset
, ptr_base
);
320 if(ptr_info
.group
!= this_info
.group
){
321 this->set_mode(is_pointee_outside
);
322 this->members
.direct
.addr
= const_cast<void*>(ptr
);
324 else if(ptr_info
.id
== this_info
.id
){
325 this->set_mode(is_relative
);
326 members
.relative
.off
= (static_cast<const char*>(ptr
) - reinterpret_cast<const char*>(this));
327 this->relative_set_begin_from_base(this_base
);
328 std::size_t pow
, frc
;
329 std::size_t s
= calculate_size(this_info
.size
, pow
, frc
);
331 assert(this_info
.size
== s
);
332 this->members
.relative
.pow
= pow
;
333 this->members
.relative
.frc
= frc
;
336 this->set_mode(is_segmented
);
337 this->members
.segmented
.segment
= ptr_info
.id
;
338 this->members
.segmented
.off
= ptr_offset
;
343 //!Sets the object internals to represent the address pointed
344 //!by another flat_map_intersegment
345 void set_from_other(const self_t
&other
)
347 this->set_from_pointer(other
.get_pointer());
350 //!Increments internal
352 void inc_offset(std::ptrdiff_t bytes
)
354 this->set_from_pointer(static_cast<char*>(this->get_pointer()) + bytes
);
357 //!Decrements internal
359 void dec_offset(std::ptrdiff_t bytes
)
361 this->set_from_pointer(static_cast<char*>(this->get_pointer()) - bytes
);
364 //////////////////////////////////////
365 //////////////////////////////////////
366 //////////////////////////////////////
368 flat_map_intersegment()
369 : intersegment_base()
372 ~flat_map_intersegment()
377 class segment_group_t
384 vector
<segment_data
> m_segments
;
385 multi_segment_services
&m_ms_services
;
388 segment_group_t(multi_segment_services
&ms_services
)
389 : m_ms_services(ms_services
)
392 void push_back(void *addr
, std::size_t size
)
394 segment_data d
= { addr
, size
};
395 m_segments
.push_back(d
);
400 assert(!m_segments
.empty());
401 m_segments
.erase(--m_segments
.end());
405 void *address_of(std::size_t segment_id
)
407 assert(segment_id
< (std::size_t)m_segments
.size());
408 return m_segments
[segment_id
].addr
;
411 void clear_segments()
412 { m_segments
.clear(); }
414 std::size_t get_size() const
415 { return m_segments
.size(); }
417 multi_segment_services
&get_multi_segment_services() const
418 { return m_ms_services
; }
420 friend bool operator< (const segment_group_t
&l
, const segment_group_t
&r
)
421 { return &l
.m_ms_services
< &r
.m_ms_services
; }
424 struct segment_info_t
428 segment_group_t
*group
;
430 : size(0), id(0), group(0)
434 typedef set
<segment_group_t
> segment_groups_t
;
436 typedef boost::interprocess::flat_map
439 ,std::less
<const void *> > ptr_to_segment_info_t
;
441 struct mappings_t
: Mutex
443 //!Mutex to preserve integrity in multi-threaded
445 typedef Mutex mutex_type
;
446 //!Maps base addresses and segment information
447 //!(size and segment group and id)*
449 ptr_to_segment_info_t m_ptr_to_segment_info
;
453 //Check that all mappings have been erased
454 assert(m_ptr_to_segment_info
.empty());
459 static mappings_t s_map
;
460 static segment_groups_t s_groups
;
463 typedef segment_group_t
* segment_group_id
;
465 //!Returns the segment and offset
467 static void get_segment_info_and_offset(const void *ptr
, segment_info_t
&segment
, std::size_t &offset
, void *&base
)
469 //------------------------------------------------------------------
470 boost::interprocess::scoped_lock
<typename
mappings_t::mutex_type
> lock(s_map
);
471 //------------------------------------------------------------------
473 if(s_map
.m_ptr_to_segment_info
.empty()){
474 segment
= segment_info_t();
475 offset
= reinterpret_cast<const char*>(ptr
) - static_cast<const char*>(0);
478 //Find the first base address greater than ptr
479 typename
ptr_to_segment_info_t::iterator it
480 = s_map
.m_ptr_to_segment_info
.upper_bound(ptr
);
481 if(it
== s_map
.m_ptr_to_segment_info
.begin()){
482 segment
= segment_info_t();
483 offset
= reinterpret_cast<const char*>(ptr
) - static_cast<const char *>(0);
485 //Go to the previous one
487 char * segment_base
= const_cast<char*>(reinterpret_cast<const char*>(it
->first
));
488 std::size_t segment_size
= it
->second
.size
;
490 if(segment_base
<= reinterpret_cast<const char*>(ptr
) &&
491 (segment_base
+ segment_size
) >= reinterpret_cast<const char*>(ptr
)){
492 segment
= it
->second
;
493 offset
= reinterpret_cast<const char*>(ptr
) - segment_base
;
497 segment
= segment_info_t();
498 offset
= reinterpret_cast<const char*>(ptr
) - static_cast<const char*>(0);
502 //!Associates a segment defined by group/id with a base address and size.
503 //!Returns false if the group is not found or there is an error
504 static void insert_mapping(segment_group_id group_id
, void *ptr
, std::size_t size
)
506 //------------------------------------------------------------------
507 boost::interprocess::scoped_lock
<typename
mappings_t::mutex_type
> lock(s_map
);
508 //------------------------------------------------------------------
510 typedef typename
ptr_to_segment_info_t::value_type value_type
;
511 typedef typename
ptr_to_segment_info_t::iterator iterator
;
512 typedef std::pair
<iterator
, bool> it_b_t
;
515 info
.group
= group_id
;
517 info
.id
= group_id
->get_size();
519 it_b_t ret
= s_map
.m_ptr_to_segment_info
.insert(value_type(ptr
, info
));
522 value_eraser
<ptr_to_segment_info_t
> v_eraser(s_map
.m_ptr_to_segment_info
, ret
.first
);
523 group_id
->push_back(ptr
, size
);
527 static bool erase_last_mapping(segment_group_id group_id
)
529 //------------------------------------------------------------------
530 boost::interprocess::scoped_lock
<typename
mappings_t::mutex_type
> lock(s_map
);
531 //------------------------------------------------------------------
532 if(!group_id
->get_size()){
536 void *addr
= group_id
->address_of(group_id
->get_size()-1);
537 group_id
->pop_back();
538 std::size_t erased
= s_map
.m_ptr_to_segment_info
.erase(addr
);
545 static segment_group_id
new_segment_group(multi_segment_services
*services
)
547 { //------------------------------------------------------------------
548 boost::interprocess::scoped_lock
<typename
mappings_t::mutex_type
> lock(s_map
);
549 //------------------------------------------------------------------
550 typedef typename
segment_groups_t::iterator iterator
;
551 std::pair
<iterator
, bool> ret
=
552 s_groups
.insert(segment_group_t(*services
));
558 static bool delete_group(segment_group_id id
)
560 { //------------------------------------------------------------------
561 boost::interprocess::scoped_lock
<typename
mappings_t::mutex_type
> lock(s_map
);
562 //------------------------------------------------------------------
563 bool success
= 1u == s_groups
.erase(segment_group_t(*id
));
565 typedef typename
ptr_to_segment_info_t::iterator ptr_to_segment_info_it
;
566 ptr_to_segment_info_it
it(s_map
.m_ptr_to_segment_info
.begin());
567 while(it
!= s_map
.m_ptr_to_segment_info
.end()){
568 if(it
->second
.group
== id
){
569 it
= s_map
.m_ptr_to_segment_info
.erase(it
);
581 //!Static map-segment_info associated with
582 //!flat_map_intersegment<>
583 template <class Mutex
>
584 typename flat_map_intersegment
<Mutex
>::mappings_t
585 flat_map_intersegment
<Mutex
>::s_map
;
587 //!Static segment group container associated with
588 //!flat_map_intersegment<>
589 template <class Mutex
>
590 typename flat_map_intersegment
<Mutex
>::segment_groups_t
591 flat_map_intersegment
<Mutex
>::s_groups
;
593 //!A smart pointer that can point to a pointee that resides in another memory
594 //!memory mapped or shared memory segment.
596 class intersegment_ptr
: public flat_map_intersegment
<interprocess_mutex
>
598 typedef flat_map_intersegment
<interprocess_mutex
> PT
;
599 typedef intersegment_ptr
<T
> self_t
;
602 void unspecified_bool_type_func() const {}
603 typedef void (self_t::*unspecified_bool_type
)() const;
607 typedef typename
detail::add_reference
<T
>::type reference
;
608 typedef T value_type
;
609 typedef std::ptrdiff_t difference_type
;
610 typedef std::random_access_iterator_tag iterator_category
;
612 public: //Public Functions
614 //!Constructor from raw pointer (allows "0" pointer conversion).
616 intersegment_ptr(pointer ptr
= 0)
617 { base_t::set_from_pointer(ptr
); }
619 //!Constructor from other pointer.
622 intersegment_ptr(U
*ptr
){ base_t::set_from_pointer(pointer(ptr
)); }
624 //!Constructor from other intersegment_ptr
626 intersegment_ptr(const intersegment_ptr
& ptr
)
627 { base_t::set_from_other(ptr
); }
629 //!Constructor from other intersegment_ptr. If pointers of pointee types are
630 //!convertible, intersegment_ptrs will be convertibles. Never throws.
632 intersegment_ptr(const intersegment_ptr
<T2
> &ptr
)
633 { pointer
p(ptr
.get()); (void)p
; base_t::set_from_other(ptr
); }
635 //!Emulates static_cast operator.
638 intersegment_ptr(const intersegment_ptr
<U
> &r
, detail::static_cast_tag
)
639 { base_t::set_from_pointer(static_cast<T
*>(r
.get())); }
641 //!Emulates const_cast operator.
644 intersegment_ptr(const intersegment_ptr
<U
> &r
, detail::const_cast_tag
)
645 { base_t::set_from_pointer(const_cast<T
*>(r
.get())); }
647 //!Emulates dynamic_cast operator.
650 intersegment_ptr(const intersegment_ptr
<U
> &r
, detail::dynamic_cast_tag
)
651 { base_t::set_from_pointer(dynamic_cast<T
*>(r
.get())); }
653 //!Emulates reinterpret_cast operator.
656 intersegment_ptr(const intersegment_ptr
<U
> &r
, detail::reinterpret_cast_tag
)
657 { base_t::set_from_pointer(reinterpret_cast<T
*>(r
.get())); }
659 //!Obtains raw pointer from offset.
662 { return static_cast<pointer
>(base_t::get_pointer()); }
664 //!Pointer-like -> operator. It can return 0 pointer.
666 pointer
operator->() const
667 { return self_t::get(); }
669 //!Dereferencing operator, if it is a null intersegment_ptr behavior
670 //!is undefined. Never throws.
671 reference
operator* () const
672 { return *(self_t::get()); }
674 //!Indexing operator.
676 reference
operator[](std::ptrdiff_t idx
) const
677 { return self_t::get()[idx
]; }
679 //!Assignment from pointer (saves extra conversion).
681 intersegment_ptr
& operator= (pointer from
)
682 { base_t::set_from_pointer(from
); return *this; }
684 //!Assignment from other intersegment_ptr.
686 intersegment_ptr
& operator= (const intersegment_ptr
&ptr
)
687 { base_t::set_from_other(ptr
); return *this; }
689 //!Assignment from related intersegment_ptr. If pointers of pointee types
690 //!are assignable, intersegment_ptrs will be assignable. Never throws.
692 intersegment_ptr
& operator= (const intersegment_ptr
<T2
> & ptr
)
694 pointer
p(ptr
.get()); (void)p
;
695 base_t::set_from_other(ptr
); return *this;
698 //!intersegment_ptr + std::ptrdiff_t.
700 intersegment_ptr
operator+ (std::ptrdiff_t idx
) const
702 intersegment_ptr
result (*this);
703 result
.inc_offset(idx
*sizeof(T
));
707 //!intersegment_ptr - std::ptrdiff_t.
709 intersegment_ptr
operator- (std::ptrdiff_t idx
) const
711 intersegment_ptr
result (*this);
712 result
.dec_offset(idx
*sizeof(T
));
716 //!intersegment_ptr += std::ptrdiff_t.
718 intersegment_ptr
&operator+= (std::ptrdiff_t offset
)
719 { base_t::inc_offset(offset
*sizeof(T
)); return *this; }
721 //!intersegment_ptr -= std::ptrdiff_t.
723 intersegment_ptr
&operator-= (std::ptrdiff_t offset
)
724 { base_t::dec_offset(offset
*sizeof(T
)); return *this; }
726 //!++intersegment_ptr.
728 intersegment_ptr
& operator++ (void)
729 { base_t::inc_offset(sizeof(T
)); return *this; }
731 //!intersegment_ptr++.
733 intersegment_ptr
operator++ (int)
734 { intersegment_ptr
temp(*this); ++*this; return temp
; }
736 //!--intersegment_ptr.
738 intersegment_ptr
& operator-- (void)
739 { base_t::dec_offset(sizeof(T
)); return *this; }
741 //!intersegment_ptr--.
743 intersegment_ptr
operator-- (int)
744 { intersegment_ptr
temp(*this); --*this; return temp
; }
746 //!Safe bool conversion operator.
748 operator unspecified_bool_type() const
749 { return base_t::is_null()? 0 : &self_t::unspecified_bool_type_func
; }
751 //!Not operator. Not needed in theory, but improves portability.
753 bool operator! () const
754 { return base_t::is_null(); }
756 //!Swaps two intersegment_ptr-s. More efficient than std::swap.
758 void swap(intersegment_ptr
&other
)
759 { base_t::swap(other
); }
761 //!Calculates the distance between two intersegment_ptr-s.
762 //!This only works with two basic_intersegment_ptr pointing
763 //!to the same segment. Otherwise undefined
765 ptrdiff_t _diff(const intersegment_ptr
<T2
> &other
) const
766 { return base_t::diff(other
); }
768 //!Returns true if both point to the
771 bool _equal(const intersegment_ptr
<T2
>&other
) const
772 { return base_t::equal(other
); }
774 //!Returns true if *this is less than other.
775 //!This only works with two basic_intersegment_ptr pointing
776 //!to the same segment group. Otherwise undefined. Never throws
778 bool _less(const intersegment_ptr
<T2
> &other
) const
779 { return base_t::less(other
); }
782 //!Compares the equality of two intersegment_ptr-s.
784 template <class T1
, class T2
> inline
785 bool operator ==(const intersegment_ptr
<T1
> &left
,
786 const intersegment_ptr
<T2
> &right
)
788 //Make sure both pointers can be compared
789 bool e
= typename intersegment_ptr
<T1
>::pointer(0) ==
790 typename intersegment_ptr
<T2
>::pointer(0);
792 return left
._equal(right
);
795 //!Returns true if *this is less than other.
796 //!This only works with two basic_intersegment_ptr pointing
797 //!to the same segment group. Otherwise undefined. Never throws
798 template <class T1
, class T2
> inline
799 bool operator <(const intersegment_ptr
<T1
> &left
,
800 const intersegment_ptr
<T2
> &right
)
802 //Make sure both pointers can be compared
803 bool e
= typename intersegment_ptr
<T1
>::pointer(0) <
804 typename intersegment_ptr
<T2
>::pointer(0);
806 return left
._less(right
);
809 template<class T1
, class T2
> inline
810 bool operator!= (const intersegment_ptr
<T1
> &pt1
,
811 const intersegment_ptr
<T2
> &pt2
)
812 { return !(pt1
==pt2
); }
814 //!intersegment_ptr<T1> <= intersegment_ptr<T2>.
816 template<class T1
, class T2
> inline
817 bool operator<= (const intersegment_ptr
<T1
> &pt1
,
818 const intersegment_ptr
<T2
> &pt2
)
819 { return !(pt1
> pt2
); }
821 //!intersegment_ptr<T1> > intersegment_ptr<T2>.
823 template<class T1
, class T2
> inline
824 bool operator> (const intersegment_ptr
<T1
> &pt1
,
825 const intersegment_ptr
<T2
> &pt2
)
826 { return (pt2
< pt1
); }
828 //!intersegment_ptr<T1> >= intersegment_ptr<T2>.
830 template<class T1
, class T2
> inline
831 bool operator>= (const intersegment_ptr
<T1
> &pt1
,
832 const intersegment_ptr
<T2
> &pt2
)
833 { return !(pt1
< pt2
); }
836 template<class E
, class T
, class U
> inline
837 std::basic_ostream
<E
, T
> & operator<<
838 (std::basic_ostream
<E
, T
> & os
, const intersegment_ptr
<U
> & p
)
839 { return os
<< p
.get(); }
842 template<class E
, class T
, class U
> inline
843 std::basic_istream
<E
, T
> & operator>>
844 (std::basic_istream
<E
, T
> & os
, intersegment_ptr
<U
> & p
)
845 { U
* tmp
; return os
>> tmp
; p
= tmp
; }
847 //!std::ptrdiff_t + intersegment_ptr.
848 //!The result is another pointer of the same segment
849 template<class T
> inline
850 intersegment_ptr
<T
> operator+
851 (std::ptrdiff_t diff
, const intersegment_ptr
<T
>& right
)
852 { return right
+ diff
; }
854 //!intersegment_ptr - intersegment_ptr.
855 //!This only works with two intersegment_ptr-s that point to the
857 template <class T
, class T2
> inline
858 std::ptrdiff_t operator- (const intersegment_ptr
<T
> &pt
,
859 const intersegment_ptr
<T2
> &pt2
)
860 { return pt
._diff(pt2
)/sizeof(T
); }
862 //! swap specialization
863 template<class T
> inline
864 void swap (boost::interprocess::intersegment_ptr
<T
> &pt
,
865 boost::interprocess::intersegment_ptr
<T
> &pt2
)
868 //!get_pointer() enables boost::mem_fn to recognize intersegment_ptr.
870 template<class T
> inline
871 T
* get_pointer(boost::interprocess::intersegment_ptr
<T
> const & p
)
874 //!Simulation of static_cast between pointers.
876 template<class T
, class U
> inline
877 boost::interprocess::intersegment_ptr
<T
> static_pointer_cast(const boost::interprocess::intersegment_ptr
<U
> &r
)
878 { return boost::interprocess::intersegment_ptr
<T
>(r
, boost::interprocess::detail::static_cast_tag()); }
880 //!Simulation of const_cast between pointers.
882 template<class T
, class U
> inline
883 boost::interprocess::intersegment_ptr
<T
> const_pointer_cast(const boost::interprocess::intersegment_ptr
<U
> &r
)
884 { return boost::interprocess::intersegment_ptr
<T
>(r
, boost::interprocess::detail::const_cast_tag()); }
886 //!Simulation of dynamic_cast between pointers.
888 template<class T
, class U
> inline
889 boost::interprocess::intersegment_ptr
<T
> dynamic_pointer_cast(const boost::interprocess::intersegment_ptr
<U
> &r
)
890 { return boost::interprocess::intersegment_ptr
<T
>(r
, boost::interprocess::detail::dynamic_cast_tag()); }
892 //!Simulation of reinterpret_cast between pointers.
894 template<class T
, class U
> inline
895 boost::interprocess::intersegment_ptr
<T
> reinterpret_pointer_cast(const boost::interprocess::intersegment_ptr
<U
> &r
)
896 { return boost::interprocess::intersegment_ptr
<T
>(r
, boost::interprocess::detail::reinterpret_cast_tag()); }
898 //!Trait class to detect if an smart pointer has
899 //!multi-segment addressing capabilities.
901 struct is_multisegment_ptr
902 <boost::interprocess::intersegment_ptr
<T
> >
904 static const bool value
= true;
907 } //namespace interprocess {
909 #if defined(_MSC_VER) && (_MSC_VER < 1400)
910 //!get_pointer() enables boost::mem_fn to recognize intersegment_ptr.
912 template<class T
> inline
913 T
* get_pointer(boost::interprocess::intersegment_ptr
<T
> const & p
)
917 //!has_trivial_constructor<> == true_type specialization
920 struct has_trivial_constructor
921 < boost::interprocess::intersegment_ptr
<T
> >
922 : public true_type
{};
924 //!has_trivial_destructor<> == true_type specialization
927 struct has_trivial_destructor
928 < boost::interprocess::intersegment_ptr
<T
> >
929 : public true_type
{};
931 } //namespace boost {
933 #include <boost/interprocess/detail/config_end.hpp>
941 //-> is_pointee_outside
950 // std::size_t ctrl : CTRL_BITS;
951 // std::size_t segment : MAX_SEGMENT_BITS;
952 // std::size_t offset;
954 //RELATIVE_SIZE_BITS = SIZE_T_BITS -
955 // MAX_SEGMENT_BITS -
957 //MAX_SEGMENT_SIZE = SIZE_T_BITS - ALIGN_BITS 20 52
959 //SIZE_T_BITS - 1 - ALIGN_BITS 19 51
960 //POW_SIZE_BITS = upper_log2
961 // (SIZE_T_BITS - 1 - ALIGN_BITS) 5 6
962 //FRC_SIZE_BITS = SIZE_T_BITS - CTRL_BITS
963 // MAX_SEGMENT_SIZE_ALIGNBITS - POW_SIZE_BITS 6 5
967 // std::size_t ctrl : CTRL_BITS; 2 2
968 // std::size_t size_pow : POW_SIZE_BITS 5 6
969 // std::size_t size_frc : FRC_SIZE_BITS; 6 5
970 // std::size_t start : MAX_SEGMENT_SIZE_ALIGNBITS;19 51
971 // std::ptrdiff_t distance : SIZE_T_BITS; 32 64
975 // std::size_t ctrl : CTRL_BITS; 2 2
976 // std::size_t dummy : SIZE_T_BITS - CTRL_BITS 30 62
977 // void *addr : SIZE_T_BITS; 32 64
980 //Page alignment: 2**12
983 //!Obtains the address pointed by the
985 void *get_pointer() const
987 if(this->is_pointee_outside() || this->is_in_stack()){
988 return raw_address();
990 else if(this->is_relative()){
991 return (const_cast<char*>(reinterpret_cast<const char*>(this))) + this->relative_pointee_offset();
994 group_manager
*m
= get_segment_group_manager(addr
);
995 char *base
= static_cast<char*>(m
->get_id_address(this->segmented_id()));
996 return base
+ this->segmented_offset();
1000 void set_from_pointer(const void *ptr
)
1003 this->set_pointee_outside();
1004 this->raw_address(ptr
);
1006 else if(this->is_in_stack()){
1007 this->raw_address(ptr
);
1009 else if(this->is_relative() &&
1010 ( (ptr
>= this->relative_start())
1011 &&(ptr
< this->relative_start() + this->relative_size()))
1013 this->relative_offset(ptr
- this);
1016 segment_info_t ptr_info
= get_id_from_addr(ptr
);
1017 segment_info_t this_info
= get_id_from_addr(this);
1018 if(ptr_info
.segment_group
!= this_info
.segment_group
){
1019 if(!ptr_info
.segment_group
){
1020 this->set_in_stack();
1023 this->set_pointee_outside();
1026 else if(ptr_info
.segment_id
== this_info
.segment_id
){
1028 this->relative_size (ptr_info
.size
);
1029 this->relative_offset(static_cast<const char*>(ptr
) - reinterpret_cast<const char*>(this));
1030 this->relative_start (ptr_info
.base
);
1035 void set_from_other(const self_t
&other
)
1036 { this->set_from_pointer(other
.get_pointer()); }
1040 #endif //#ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP