Chris@16
|
1 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 //
|
Chris@16
|
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
|
Chris@16
|
4 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 //
|
Chris@16
|
7 // See http://www.boost.org/libs/interprocess for documentation.
|
Chris@16
|
8 //
|
Chris@16
|
9 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP
|
Chris@16
|
12 #define BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP
|
Chris@16
|
13
|
Chris@101
|
14 #ifndef BOOST_CONFIG_HPP
|
Chris@101
|
15 # include <boost/config.hpp>
|
Chris@101
|
16 #endif
|
Chris@101
|
17 #
|
Chris@101
|
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
|
Chris@16
|
19 # pragma once
|
Chris@16
|
20 #endif
|
Chris@16
|
21
|
Chris@16
|
22 #include <boost/interprocess/detail/config_begin.hpp>
|
Chris@16
|
23 #include <boost/interprocess/detail/workaround.hpp>
|
Chris@101
|
24 // interprocess
|
Chris@16
|
25 #include <boost/interprocess/interprocess_fwd.hpp>
|
Chris@16
|
26 #include <boost/interprocess/sync/scoped_lock.hpp>
|
Chris@16
|
27 #include <boost/interprocess/sync/interprocess_mutex.hpp>
|
Chris@16
|
28 #include <boost/interprocess/containers/flat_map.hpp>
|
Chris@16
|
29 #include <boost/interprocess/containers/vector.hpp> //vector
|
Chris@16
|
30 #include <boost/interprocess/containers/set.hpp> //set
|
Chris@101
|
31 // interprocess/detail
|
Chris@101
|
32 #include <boost/interprocess/detail/multi_segment_services.hpp>
|
Chris@101
|
33 #include <boost/interprocess/detail/utilities.hpp>
|
Chris@101
|
34 #include <boost/interprocess/detail/math_functions.hpp>
|
Chris@101
|
35 #include <boost/interprocess/detail/cast_tags.hpp>
|
Chris@16
|
36 #include <boost/interprocess/detail/mpl.hpp>
|
Chris@101
|
37 // other boost
|
Chris@101
|
38 #include <boost/core/no_exceptions_support.hpp>
|
Chris@16
|
39 #include <boost/static_assert.hpp> //BOOST_STATIC_ASSERT
|
Chris@16
|
40 #include <boost/integer/static_log2.hpp>
|
Chris@16
|
41 #include <boost/assert.hpp> //BOOST_ASSERT
|
Chris@101
|
42 // std
|
Chris@101
|
43 #include <climits> //CHAR_BIT
|
Chris@16
|
44
|
Chris@16
|
45 //!\file
|
Chris@16
|
46 //!
|
Chris@16
|
47 namespace boost {
|
Chris@16
|
48
|
Chris@16
|
49 //Predeclarations
|
Chris@16
|
50 template <class T>
|
Chris@16
|
51 struct has_trivial_constructor;
|
Chris@16
|
52
|
Chris@16
|
53 template <class T>
|
Chris@16
|
54 struct has_trivial_destructor;
|
Chris@16
|
55
|
Chris@16
|
56 namespace interprocess {
|
Chris@16
|
57
|
Chris@16
|
58 template <class T>
|
Chris@16
|
59 struct is_multisegment_ptr;
|
Chris@16
|
60
|
Chris@16
|
61 struct intersegment_base
|
Chris@16
|
62 {
|
Chris@16
|
63 typedef intersegment_base self_t;
|
Chris@16
|
64 BOOST_STATIC_ASSERT((sizeof(std::size_t) == sizeof(void*)));
|
Chris@16
|
65 BOOST_STATIC_ASSERT((sizeof(void*)*CHAR_BIT == 32 || sizeof(void*)*CHAR_BIT == 64));
|
Chris@16
|
66 static const std::size_t size_t_bits = (sizeof(void*)*CHAR_BIT == 32) ? 32 : 64;
|
Chris@16
|
67 static const std::size_t ctrl_bits = 2;
|
Chris@16
|
68 static const std::size_t align_bits = 12;
|
Chris@16
|
69 static const std::size_t align = std::size_t(1) << align_bits;
|
Chris@16
|
70 static const std::size_t max_segment_size_bits = size_t_bits - 2;
|
Chris@16
|
71 static const std::size_t max_segment_size = std::size_t(1) << max_segment_size_bits;
|
Chris@16
|
72
|
Chris@16
|
73 static const std::size_t begin_bits = max_segment_size_bits - align_bits;
|
Chris@16
|
74 static const std::size_t pow_size_bits_helper = static_log2<max_segment_size_bits>::value;
|
Chris@16
|
75 static const std::size_t pow_size_bits =
|
Chris@16
|
76 (max_segment_size_bits == (std::size_t(1) << pow_size_bits_helper)) ?
|
Chris@16
|
77 pow_size_bits_helper : pow_size_bits_helper + 1;
|
Chris@16
|
78 static const std::size_t frc_size_bits =
|
Chris@16
|
79 size_t_bits - ctrl_bits - begin_bits - pow_size_bits;
|
Chris@16
|
80
|
Chris@16
|
81 BOOST_STATIC_ASSERT(((size_t_bits - pow_size_bits - frc_size_bits) >= ctrl_bits ));
|
Chris@16
|
82
|
Chris@16
|
83 static const std::size_t relative_size_bits =
|
Chris@16
|
84 size_t_bits - max_segment_size_bits - ctrl_bits;
|
Chris@16
|
85
|
Chris@16
|
86 static const std::size_t is_pointee_outside = 0;
|
Chris@16
|
87 static const std::size_t is_in_stack = 1;
|
Chris@16
|
88 static const std::size_t is_relative = 2;
|
Chris@16
|
89 static const std::size_t is_segmented = 3;
|
Chris@16
|
90 static const std::size_t is_max_mode = 4;
|
Chris@16
|
91
|
Chris@16
|
92 intersegment_base()
|
Chris@16
|
93 {
|
Chris@16
|
94 this->set_mode(is_pointee_outside);
|
Chris@16
|
95 this->set_null();
|
Chris@16
|
96 }
|
Chris@16
|
97
|
Chris@16
|
98 struct relative_addressing
|
Chris@16
|
99 {
|
Chris@16
|
100 std::size_t ctrl : 2;
|
Chris@16
|
101 std::size_t pow : pow_size_bits;
|
Chris@16
|
102 std::size_t frc : frc_size_bits;
|
Chris@16
|
103 std::size_t beg : begin_bits;
|
Chris@16
|
104 std::ptrdiff_t off : sizeof(std::ptrdiff_t)*CHAR_BIT - 2;
|
Chris@16
|
105 std::ptrdiff_t bits : 2;
|
Chris@16
|
106 };
|
Chris@16
|
107
|
Chris@16
|
108 struct direct_addressing
|
Chris@16
|
109 {
|
Chris@16
|
110 std::size_t ctrl : 2;
|
Chris@16
|
111 std::size_t dummy : sizeof(std::size_t)*CHAR_BIT - 2;
|
Chris@16
|
112 void * addr;
|
Chris@16
|
113 };
|
Chris@16
|
114
|
Chris@16
|
115 struct segmented_addressing
|
Chris@16
|
116 {
|
Chris@16
|
117 std::size_t ctrl : 2;
|
Chris@16
|
118 std::size_t segment : sizeof(std::size_t)*CHAR_BIT - 2;
|
Chris@16
|
119 std::size_t off : sizeof(std::size_t)*CHAR_BIT - 2;
|
Chris@16
|
120 std::size_t bits : 2;
|
Chris@16
|
121 };
|
Chris@16
|
122
|
Chris@16
|
123 union members_t{
|
Chris@16
|
124 relative_addressing relative;
|
Chris@16
|
125 direct_addressing direct;
|
Chris@16
|
126 segmented_addressing segmented;
|
Chris@16
|
127 } members;
|
Chris@16
|
128
|
Chris@16
|
129 BOOST_STATIC_ASSERT(sizeof(members_t) == 2*sizeof(std::size_t));
|
Chris@16
|
130
|
Chris@16
|
131 void *relative_calculate_begin_addr() const
|
Chris@16
|
132 {
|
Chris@16
|
133 const std::size_t mask = ~(align - 1);
|
Chris@16
|
134 std::size_t beg = this->members.relative.beg;
|
Chris@16
|
135 return reinterpret_cast<void*>((((std::size_t)this) & mask) - (beg << align_bits));
|
Chris@16
|
136 }
|
Chris@16
|
137
|
Chris@16
|
138 void relative_set_begin_from_base(void *addr)
|
Chris@16
|
139 {
|
Chris@16
|
140 BOOST_ASSERT(addr < static_cast<void*>(this));
|
Chris@16
|
141 std::size_t off = reinterpret_cast<char*>(this) - reinterpret_cast<char*>(addr);
|
Chris@16
|
142 members.relative.beg = off >> align_bits;
|
Chris@16
|
143 }
|
Chris@16
|
144
|
Chris@16
|
145 //!Obtains the address pointed by the
|
Chris@16
|
146 //!object
|
Chris@16
|
147 std::size_t relative_size() const
|
Chris@16
|
148 {
|
Chris@16
|
149 std::size_t pow = members.relative.pow;
|
Chris@16
|
150 std::size_t size = (std::size_t(1u) << pow);
|
Chris@16
|
151 BOOST_ASSERT(pow >= frc_size_bits);
|
Chris@16
|
152 size |= members.relative.frc << (pow - frc_size_bits);
|
Chris@16
|
153 return size;
|
Chris@16
|
154 }
|
Chris@16
|
155
|
Chris@16
|
156 static std::size_t calculate_size(std::size_t orig_size, std::size_t &pow, std::size_t &frc)
|
Chris@16
|
157 {
|
Chris@16
|
158 if(orig_size < align)
|
Chris@16
|
159 orig_size = align;
|
Chris@16
|
160 orig_size = ipcdetail::get_rounded_size_po2(orig_size, align);
|
Chris@16
|
161 pow = ipcdetail::floor_log2(orig_size);
|
Chris@16
|
162 std::size_t low_size = (std::size_t(1) << pow);
|
Chris@16
|
163 std::size_t diff = orig_size - low_size;
|
Chris@16
|
164 BOOST_ASSERT(pow >= frc_size_bits);
|
Chris@16
|
165 std::size_t rounded = ipcdetail::get_rounded_size_po2
|
Chris@16
|
166 (diff, (std::size_t)(1u << (pow - frc_size_bits)));
|
Chris@16
|
167 if(rounded == low_size){
|
Chris@16
|
168 ++pow;
|
Chris@16
|
169 frc = 0;
|
Chris@16
|
170 rounded = 0;
|
Chris@16
|
171 }
|
Chris@16
|
172 else{
|
Chris@16
|
173 frc = rounded >> (pow - frc_size_bits);
|
Chris@16
|
174 }
|
Chris@16
|
175 BOOST_ASSERT(((frc << (pow - frc_size_bits)) & (align-1))==0);
|
Chris@16
|
176 return low_size + rounded;
|
Chris@16
|
177 }
|
Chris@16
|
178
|
Chris@16
|
179 std::size_t get_mode()const
|
Chris@16
|
180 { return members.direct.ctrl; }
|
Chris@16
|
181
|
Chris@16
|
182 void set_mode(std::size_t mode)
|
Chris@16
|
183 {
|
Chris@16
|
184 BOOST_ASSERT(mode < is_max_mode);
|
Chris@16
|
185 members.direct.ctrl = mode;
|
Chris@16
|
186 }
|
Chris@16
|
187
|
Chris@16
|
188 //!Returns true if object represents
|
Chris@16
|
189 //!null pointer
|
Chris@16
|
190 bool is_null() const
|
Chris@16
|
191 {
|
Chris@16
|
192 return (this->get_mode() < is_relative) &&
|
Chris@16
|
193 !members.direct.dummy &&
|
Chris@16
|
194 !members.direct.addr;
|
Chris@16
|
195 }
|
Chris@16
|
196
|
Chris@16
|
197 //!Sets the object to represent
|
Chris@16
|
198 //!the null pointer
|
Chris@16
|
199 void set_null()
|
Chris@16
|
200 {
|
Chris@16
|
201 if(this->get_mode() >= is_relative){
|
Chris@16
|
202 this->set_mode(is_pointee_outside);
|
Chris@16
|
203 }
|
Chris@16
|
204 members.direct.dummy = 0;
|
Chris@16
|
205 members.direct.addr = 0;
|
Chris@16
|
206 }
|
Chris@16
|
207
|
Chris@16
|
208 static std::size_t round_size(std::size_t orig_size)
|
Chris@16
|
209 {
|
Chris@16
|
210 std::size_t pow, frc;
|
Chris@16
|
211 return calculate_size(orig_size, pow, frc);
|
Chris@16
|
212 }
|
Chris@16
|
213 };
|
Chris@16
|
214
|
Chris@16
|
215
|
Chris@16
|
216
|
Chris@16
|
217 //!Configures intersegment_ptr with the capability to address:
|
Chris@16
|
218 //!2^(sizeof(std::size_t)*CHAR_BIT/2) segment groups
|
Chris@16
|
219 //!2^(sizeof(std::size_t)*CHAR_BIT/2) segments per group.
|
Chris@16
|
220 //!2^(sizeof(std::size_t)*CHAR_BIT/2)-1 bytes maximum per segment.
|
Chris@16
|
221 //!The mapping is implemented through flat_maps synchronized with mutexes.
|
Chris@16
|
222 template <class Mutex>
|
Chris@16
|
223 struct flat_map_intersegment
|
Chris@16
|
224 : public intersegment_base
|
Chris@16
|
225 {
|
Chris@16
|
226 typedef flat_map_intersegment<Mutex> self_t;
|
Chris@16
|
227
|
Chris@16
|
228 void set_from_pointer(const volatile void *ptr)
|
Chris@16
|
229 { this->set_from_pointer(const_cast<const void *>(ptr)); }
|
Chris@16
|
230
|
Chris@16
|
231 //!Obtains the address pointed
|
Chris@16
|
232 //!by the object
|
Chris@16
|
233 void *to_raw_pointer() const
|
Chris@16
|
234 {
|
Chris@16
|
235 if(is_null()){
|
Chris@16
|
236 return 0;
|
Chris@16
|
237 }
|
Chris@16
|
238 switch(this->get_mode()){
|
Chris@16
|
239 case is_relative:
|
Chris@16
|
240 return const_cast<char*>(reinterpret_cast<const char*>(this)) + members.relative.off;
|
Chris@16
|
241 break;
|
Chris@16
|
242 case is_segmented:
|
Chris@16
|
243 {
|
Chris@16
|
244 segment_info_t segment_info;
|
Chris@16
|
245 std::size_t offset;
|
Chris@16
|
246 void *this_base;
|
Chris@16
|
247 get_segment_info_and_offset(this, segment_info, offset, this_base);
|
Chris@16
|
248 char *base = static_cast<char*>(segment_info.group->address_of(this->members.segmented.segment));
|
Chris@16
|
249 return base + this->members.segmented.off;
|
Chris@16
|
250 }
|
Chris@16
|
251 break;
|
Chris@16
|
252 case is_in_stack:
|
Chris@16
|
253 case is_pointee_outside:
|
Chris@16
|
254 return members.direct.addr;
|
Chris@16
|
255 break;
|
Chris@16
|
256 default:
|
Chris@16
|
257 return 0;
|
Chris@16
|
258 break;
|
Chris@16
|
259 }
|
Chris@16
|
260 }
|
Chris@16
|
261
|
Chris@16
|
262 //!Calculates the distance between two basic_intersegment_ptr-s.
|
Chris@16
|
263 //!This only works with two basic_intersegment_ptr pointing
|
Chris@16
|
264 //!to the same segment. Otherwise undefined
|
Chris@16
|
265 std::ptrdiff_t diff(const self_t &other) const
|
Chris@16
|
266 { return static_cast<char*>(this->to_raw_pointer()) - static_cast<char*>(other.to_raw_pointer()); }
|
Chris@16
|
267
|
Chris@16
|
268 //!Returns true if both point to
|
Chris@16
|
269 //!the same object
|
Chris@16
|
270 bool equal(const self_t &y) const
|
Chris@16
|
271 { return this->to_raw_pointer() == y.to_raw_pointer(); }
|
Chris@16
|
272
|
Chris@16
|
273 //!Returns true if *this is less than other.
|
Chris@16
|
274 //!This only works with two basic_intersegment_ptr pointing
|
Chris@16
|
275 //!to the same segment group. Otherwise undefined. Never throws
|
Chris@16
|
276 bool less(const self_t &y) const
|
Chris@16
|
277 { return this->to_raw_pointer() < y.to_raw_pointer(); }
|
Chris@16
|
278
|
Chris@16
|
279 void swap(self_t &other)
|
Chris@16
|
280 {
|
Chris@16
|
281 void *ptr_this = this->to_raw_pointer();
|
Chris@16
|
282 void *ptr_other = other.to_raw_pointer();
|
Chris@16
|
283 other.set_from_pointer(ptr_this);
|
Chris@16
|
284 this->set_from_pointer(ptr_other);
|
Chris@16
|
285 }
|
Chris@16
|
286
|
Chris@16
|
287 //!Sets the object internals to represent the
|
Chris@16
|
288 //!address pointed by ptr
|
Chris@16
|
289 void set_from_pointer(const void *ptr)
|
Chris@16
|
290 {
|
Chris@16
|
291 if(!ptr){
|
Chris@16
|
292 this->set_null();
|
Chris@16
|
293 return;
|
Chris@16
|
294 }
|
Chris@16
|
295
|
Chris@16
|
296 std::size_t mode = this->get_mode();
|
Chris@16
|
297 if(mode == is_in_stack){
|
Chris@16
|
298 members.direct.addr = const_cast<void*>(ptr);
|
Chris@16
|
299 return;
|
Chris@16
|
300 }
|
Chris@16
|
301 if(mode == is_relative){
|
Chris@16
|
302 char *beg_addr = static_cast<char*>(this->relative_calculate_begin_addr());
|
Chris@16
|
303 std::size_t seg_size = this->relative_size();
|
Chris@16
|
304 if(ptr >= beg_addr && ptr < (beg_addr + seg_size)){
|
Chris@16
|
305 members.relative.off = static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this);
|
Chris@16
|
306 return;
|
Chris@16
|
307 }
|
Chris@16
|
308 }
|
Chris@16
|
309 std::size_t ptr_offset;
|
Chris@16
|
310 std::size_t this_offset;
|
Chris@16
|
311 segment_info_t ptr_info;
|
Chris@16
|
312 segment_info_t this_info;
|
Chris@16
|
313 void *ptr_base;
|
Chris@16
|
314 void *this_base;
|
Chris@16
|
315 get_segment_info_and_offset(this, this_info, this_offset, this_base);
|
Chris@16
|
316
|
Chris@16
|
317 if(!this_info.group){
|
Chris@16
|
318 this->set_mode(is_in_stack);
|
Chris@16
|
319 this->members.direct.addr = const_cast<void*>(ptr);
|
Chris@16
|
320 }
|
Chris@16
|
321 else{
|
Chris@16
|
322 get_segment_info_and_offset(ptr, ptr_info, ptr_offset, ptr_base);
|
Chris@16
|
323
|
Chris@16
|
324 if(ptr_info.group != this_info.group){
|
Chris@16
|
325 this->set_mode(is_pointee_outside);
|
Chris@16
|
326 this->members.direct.addr = const_cast<void*>(ptr);
|
Chris@16
|
327 }
|
Chris@16
|
328 else if(ptr_info.id == this_info.id){
|
Chris@16
|
329 this->set_mode(is_relative);
|
Chris@16
|
330 members.relative.off = (static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this));
|
Chris@16
|
331 this->relative_set_begin_from_base(this_base);
|
Chris@16
|
332 std::size_t pow, frc;
|
Chris@16
|
333 std::size_t s = calculate_size(this_info.size, pow, frc);
|
Chris@16
|
334 (void)s;
|
Chris@16
|
335 BOOST_ASSERT(this_info.size == s);
|
Chris@16
|
336 this->members.relative.pow = pow;
|
Chris@16
|
337 this->members.relative.frc = frc;
|
Chris@16
|
338 }
|
Chris@16
|
339 else{
|
Chris@16
|
340 this->set_mode(is_segmented);
|
Chris@16
|
341 this->members.segmented.segment = ptr_info.id;
|
Chris@16
|
342 this->members.segmented.off = ptr_offset;
|
Chris@16
|
343 }
|
Chris@16
|
344 }
|
Chris@16
|
345 }
|
Chris@16
|
346
|
Chris@16
|
347 //!Sets the object internals to represent the address pointed
|
Chris@16
|
348 //!by another flat_map_intersegment
|
Chris@16
|
349 void set_from_other(const self_t &other)
|
Chris@16
|
350 {
|
Chris@16
|
351 this->set_from_pointer(other.to_raw_pointer());
|
Chris@16
|
352 }
|
Chris@16
|
353
|
Chris@16
|
354 //!Increments internal
|
Chris@16
|
355 //!offset
|
Chris@16
|
356 void inc_offset(std::ptrdiff_t bytes)
|
Chris@16
|
357 {
|
Chris@16
|
358 this->set_from_pointer(static_cast<char*>(this->to_raw_pointer()) + bytes);
|
Chris@16
|
359 }
|
Chris@16
|
360
|
Chris@16
|
361 //!Decrements internal
|
Chris@16
|
362 //!offset
|
Chris@16
|
363 void dec_offset(std::ptrdiff_t bytes)
|
Chris@16
|
364 {
|
Chris@16
|
365 this->set_from_pointer(static_cast<char*>(this->to_raw_pointer()) - bytes);
|
Chris@16
|
366 }
|
Chris@16
|
367
|
Chris@16
|
368 //////////////////////////////////////
|
Chris@16
|
369 //////////////////////////////////////
|
Chris@16
|
370 //////////////////////////////////////
|
Chris@16
|
371
|
Chris@16
|
372 flat_map_intersegment()
|
Chris@16
|
373 : intersegment_base()
|
Chris@16
|
374 {}
|
Chris@16
|
375
|
Chris@16
|
376 ~flat_map_intersegment()
|
Chris@16
|
377 {}
|
Chris@16
|
378
|
Chris@16
|
379 private:
|
Chris@16
|
380
|
Chris@16
|
381 class segment_group_t
|
Chris@16
|
382 {
|
Chris@16
|
383 struct segment_data
|
Chris@16
|
384 {
|
Chris@16
|
385 void *addr;
|
Chris@16
|
386 std::size_t size;
|
Chris@16
|
387 };
|
Chris@16
|
388 vector<segment_data> m_segments;
|
Chris@16
|
389 multi_segment_services &m_ms_services;
|
Chris@16
|
390
|
Chris@16
|
391 public:
|
Chris@16
|
392 segment_group_t(multi_segment_services &ms_services)
|
Chris@16
|
393 : m_ms_services(ms_services)
|
Chris@16
|
394 {}
|
Chris@16
|
395
|
Chris@16
|
396 void push_back(void *addr, std::size_t size)
|
Chris@16
|
397 {
|
Chris@16
|
398 segment_data d = { addr, size };
|
Chris@16
|
399 m_segments.push_back(d);
|
Chris@16
|
400 }
|
Chris@16
|
401
|
Chris@16
|
402 void pop_back()
|
Chris@16
|
403 {
|
Chris@16
|
404 BOOST_ASSERT(!m_segments.empty());
|
Chris@16
|
405 m_segments.erase(--m_segments.end());
|
Chris@16
|
406 }
|
Chris@16
|
407
|
Chris@16
|
408
|
Chris@16
|
409 void *address_of(std::size_t segment_id)
|
Chris@16
|
410 {
|
Chris@16
|
411 BOOST_ASSERT(segment_id < (std::size_t)m_segments.size());
|
Chris@16
|
412 return m_segments[segment_id].addr;
|
Chris@16
|
413 }
|
Chris@16
|
414
|
Chris@16
|
415 void clear_segments()
|
Chris@16
|
416 { m_segments.clear(); }
|
Chris@16
|
417
|
Chris@16
|
418 std::size_t get_size() const
|
Chris@16
|
419 { return m_segments.size(); }
|
Chris@16
|
420
|
Chris@16
|
421 multi_segment_services &get_multi_segment_services() const
|
Chris@16
|
422 { return m_ms_services; }
|
Chris@16
|
423
|
Chris@16
|
424 friend bool operator< (const segment_group_t&l, const segment_group_t &r)
|
Chris@16
|
425 { return &l.m_ms_services < &r.m_ms_services; }
|
Chris@16
|
426 };
|
Chris@16
|
427
|
Chris@16
|
428 struct segment_info_t
|
Chris@16
|
429 {
|
Chris@16
|
430 std::size_t size;
|
Chris@16
|
431 std::size_t id;
|
Chris@16
|
432 segment_group_t *group;
|
Chris@16
|
433 segment_info_t()
|
Chris@16
|
434 : size(0), id(0), group(0)
|
Chris@16
|
435 {}
|
Chris@16
|
436 };
|
Chris@16
|
437
|
Chris@16
|
438 typedef set<segment_group_t> segment_groups_t;
|
Chris@16
|
439
|
Chris@16
|
440 typedef boost::interprocess::flat_map
|
Chris@16
|
441 <const void *
|
Chris@16
|
442 ,segment_info_t
|
Chris@16
|
443 ,std::less<const void *> > ptr_to_segment_info_t;
|
Chris@16
|
444
|
Chris@16
|
445 struct mappings_t : Mutex
|
Chris@16
|
446 {
|
Chris@16
|
447 //!Mutex to preserve integrity in multi-threaded
|
Chris@16
|
448 //!enviroments
|
Chris@16
|
449 typedef Mutex mutex_type;
|
Chris@16
|
450 //!Maps base addresses and segment information
|
Chris@16
|
451 //!(size and segment group and id)*
|
Chris@16
|
452
|
Chris@16
|
453 ptr_to_segment_info_t m_ptr_to_segment_info;
|
Chris@16
|
454
|
Chris@16
|
455 ~mappings_t()
|
Chris@16
|
456 {
|
Chris@16
|
457 //Check that all mappings have been erased
|
Chris@16
|
458 BOOST_ASSERT(m_ptr_to_segment_info.empty());
|
Chris@16
|
459 }
|
Chris@16
|
460 };
|
Chris@16
|
461
|
Chris@16
|
462 //Static members
|
Chris@16
|
463 static mappings_t s_map;
|
Chris@16
|
464 static segment_groups_t s_groups;
|
Chris@16
|
465 public:
|
Chris@16
|
466
|
Chris@16
|
467 typedef segment_group_t* segment_group_id;
|
Chris@16
|
468
|
Chris@16
|
469 //!Returns the segment and offset
|
Chris@16
|
470 //!of an address
|
Chris@16
|
471 static void get_segment_info_and_offset(const void *ptr, segment_info_t &segment, std::size_t &offset, void *&base)
|
Chris@16
|
472 {
|
Chris@16
|
473 //------------------------------------------------------------------
|
Chris@16
|
474 boost::interprocess::scoped_lock<typename mappings_t::mutex_type> lock(s_map);
|
Chris@16
|
475 //------------------------------------------------------------------
|
Chris@16
|
476 base = 0;
|
Chris@16
|
477 if(s_map.m_ptr_to_segment_info.empty()){
|
Chris@16
|
478 segment = segment_info_t();
|
Chris@16
|
479 offset = reinterpret_cast<const char*>(ptr) - static_cast<const char*>(0);
|
Chris@16
|
480 return;
|
Chris@16
|
481 }
|
Chris@16
|
482 //Find the first base address greater than ptr
|
Chris@16
|
483 typename ptr_to_segment_info_t::iterator it
|
Chris@16
|
484 = s_map.m_ptr_to_segment_info.upper_bound(ptr);
|
Chris@16
|
485 if(it == s_map.m_ptr_to_segment_info.begin()){
|
Chris@16
|
486 segment = segment_info_t();
|
Chris@16
|
487 offset = reinterpret_cast<const char*>(ptr) - static_cast<const char *>(0);
|
Chris@16
|
488 }
|
Chris@16
|
489 //Go to the previous one
|
Chris@16
|
490 --it;
|
Chris@16
|
491 char * segment_base = const_cast<char*>(reinterpret_cast<const char*>(it->first));
|
Chris@16
|
492 std::size_t segment_size = it->second.size;
|
Chris@16
|
493
|
Chris@16
|
494 if(segment_base <= reinterpret_cast<const char*>(ptr) &&
|
Chris@16
|
495 (segment_base + segment_size) >= reinterpret_cast<const char*>(ptr)){
|
Chris@16
|
496 segment = it->second;
|
Chris@16
|
497 offset = reinterpret_cast<const char*>(ptr) - segment_base;
|
Chris@16
|
498 base = segment_base;
|
Chris@16
|
499 }
|
Chris@16
|
500 else{
|
Chris@16
|
501 segment = segment_info_t();
|
Chris@16
|
502 offset = reinterpret_cast<const char*>(ptr) - static_cast<const char*>(0);
|
Chris@16
|
503 }
|
Chris@16
|
504 }
|
Chris@16
|
505
|
Chris@16
|
506 //!Associates a segment defined by group/id with a base address and size.
|
Chris@16
|
507 //!Returns false if the group is not found or there is an error
|
Chris@16
|
508 static void insert_mapping(segment_group_id group_id, void *ptr, std::size_t size)
|
Chris@16
|
509 {
|
Chris@16
|
510 //------------------------------------------------------------------
|
Chris@16
|
511 boost::interprocess::scoped_lock<typename mappings_t::mutex_type> lock(s_map);
|
Chris@16
|
512 //------------------------------------------------------------------
|
Chris@16
|
513
|
Chris@16
|
514 typedef typename ptr_to_segment_info_t::value_type value_type;
|
Chris@16
|
515 typedef typename ptr_to_segment_info_t::iterator iterator;
|
Chris@16
|
516 typedef std::pair<iterator, bool> it_b_t;
|
Chris@16
|
517
|
Chris@16
|
518 segment_info_t info;
|
Chris@16
|
519 info.group = group_id;
|
Chris@16
|
520 info.size = size;
|
Chris@16
|
521 info.id = group_id->get_size();
|
Chris@16
|
522
|
Chris@16
|
523 it_b_t ret = s_map.m_ptr_to_segment_info.insert(value_type(ptr, info));
|
Chris@16
|
524 BOOST_ASSERT(ret.second);
|
Chris@16
|
525
|
Chris@16
|
526 value_eraser<ptr_to_segment_info_t> v_eraser(s_map.m_ptr_to_segment_info, ret.first);
|
Chris@16
|
527 group_id->push_back(ptr, size);
|
Chris@16
|
528 v_eraser.release();
|
Chris@16
|
529 }
|
Chris@16
|
530
|
Chris@16
|
531 static bool erase_last_mapping(segment_group_id group_id)
|
Chris@16
|
532 {
|
Chris@16
|
533 //------------------------------------------------------------------
|
Chris@16
|
534 boost::interprocess::scoped_lock<typename mappings_t::mutex_type> lock(s_map);
|
Chris@16
|
535 //------------------------------------------------------------------
|
Chris@16
|
536 if(!group_id->get_size()){
|
Chris@16
|
537 return false;
|
Chris@16
|
538 }
|
Chris@16
|
539 else{
|
Chris@16
|
540 void *addr = group_id->address_of(group_id->get_size()-1);
|
Chris@16
|
541 group_id->pop_back();
|
Chris@16
|
542 std::size_t erased = s_map.m_ptr_to_segment_info.erase(addr);
|
Chris@16
|
543 (void)erased;
|
Chris@16
|
544 BOOST_ASSERT(erased);
|
Chris@16
|
545 return true;
|
Chris@16
|
546 }
|
Chris@16
|
547 }
|
Chris@16
|
548
|
Chris@16
|
549 static segment_group_id new_segment_group(multi_segment_services *services)
|
Chris@16
|
550 {
|
Chris@16
|
551 { //------------------------------------------------------------------
|
Chris@16
|
552 boost::interprocess::scoped_lock<typename mappings_t::mutex_type> lock(s_map);
|
Chris@16
|
553 //------------------------------------------------------------------
|
Chris@16
|
554 typedef typename segment_groups_t::iterator iterator;
|
Chris@16
|
555 std::pair<iterator, bool> ret =
|
Chris@16
|
556 s_groups.insert(segment_group_t(*services));
|
Chris@16
|
557 BOOST_ASSERT(ret.second);
|
Chris@16
|
558 return &*ret.first;
|
Chris@16
|
559 }
|
Chris@16
|
560 }
|
Chris@16
|
561
|
Chris@16
|
562 static bool delete_group(segment_group_id id)
|
Chris@16
|
563 {
|
Chris@16
|
564 { //------------------------------------------------------------------
|
Chris@16
|
565 boost::interprocess::scoped_lock<typename mappings_t::mutex_type> lock(s_map);
|
Chris@16
|
566 //------------------------------------------------------------------
|
Chris@16
|
567 bool success = 1u == s_groups.erase(segment_group_t(*id));
|
Chris@16
|
568 if(success){
|
Chris@16
|
569 typedef typename ptr_to_segment_info_t::iterator ptr_to_segment_info_it;
|
Chris@16
|
570 ptr_to_segment_info_it it(s_map.m_ptr_to_segment_info.begin());
|
Chris@16
|
571 while(it != s_map.m_ptr_to_segment_info.end()){
|
Chris@16
|
572 if(it->second.group == id){
|
Chris@16
|
573 it = s_map.m_ptr_to_segment_info.erase(it);
|
Chris@16
|
574 }
|
Chris@16
|
575 else{
|
Chris@16
|
576 ++it;
|
Chris@16
|
577 }
|
Chris@16
|
578 }
|
Chris@16
|
579 }
|
Chris@16
|
580 return success;
|
Chris@16
|
581 }
|
Chris@16
|
582 }
|
Chris@16
|
583 };
|
Chris@16
|
584
|
Chris@16
|
585 //!Static map-segment_info associated with
|
Chris@16
|
586 //!flat_map_intersegment<>
|
Chris@16
|
587 template <class Mutex>
|
Chris@16
|
588 typename flat_map_intersegment<Mutex>::mappings_t
|
Chris@16
|
589 flat_map_intersegment<Mutex>::s_map;
|
Chris@16
|
590
|
Chris@16
|
591 //!Static segment group container associated with
|
Chris@16
|
592 //!flat_map_intersegment<>
|
Chris@16
|
593 template <class Mutex>
|
Chris@16
|
594 typename flat_map_intersegment<Mutex>::segment_groups_t
|
Chris@16
|
595 flat_map_intersegment<Mutex>::s_groups;
|
Chris@16
|
596
|
Chris@16
|
597 //!A smart pointer that can point to a pointee that resides in another memory
|
Chris@16
|
598 //!memory mapped or shared memory segment.
|
Chris@16
|
599 template <class T>
|
Chris@16
|
600 class intersegment_ptr : public flat_map_intersegment<interprocess_mutex>
|
Chris@16
|
601 {
|
Chris@16
|
602 typedef flat_map_intersegment<interprocess_mutex> PT;
|
Chris@16
|
603 typedef intersegment_ptr<T> self_t;
|
Chris@16
|
604 typedef PT base_t;
|
Chris@16
|
605
|
Chris@16
|
606 void unspecified_bool_type_func() const {}
|
Chris@16
|
607 typedef void (self_t::*unspecified_bool_type)() const;
|
Chris@16
|
608
|
Chris@16
|
609 public:
|
Chris@16
|
610 typedef T * pointer;
|
Chris@16
|
611 typedef typename ipcdetail::add_reference<T>::type reference;
|
Chris@16
|
612 typedef T value_type;
|
Chris@16
|
613 typedef std::ptrdiff_t difference_type;
|
Chris@16
|
614 typedef std::random_access_iterator_tag iterator_category;
|
Chris@16
|
615
|
Chris@16
|
616 public: //Public Functions
|
Chris@16
|
617
|
Chris@16
|
618 //!Constructor from raw pointer (allows "0" pointer conversion).
|
Chris@16
|
619 //!Never throws.
|
Chris@16
|
620 intersegment_ptr(pointer ptr = 0)
|
Chris@16
|
621 { base_t::set_from_pointer(ptr); }
|
Chris@16
|
622
|
Chris@16
|
623 //!Constructor from other pointer.
|
Chris@16
|
624 //!Never throws.
|
Chris@16
|
625 template <class U>
|
Chris@16
|
626 intersegment_ptr(U *ptr){ base_t::set_from_pointer(pointer(ptr)); }
|
Chris@16
|
627
|
Chris@16
|
628 //!Constructor from other intersegment_ptr
|
Chris@16
|
629 //!Never throws
|
Chris@16
|
630 intersegment_ptr(const intersegment_ptr& ptr)
|
Chris@16
|
631 { base_t::set_from_other(ptr); }
|
Chris@16
|
632
|
Chris@16
|
633 //!Constructor from other intersegment_ptr. If pointers of pointee types are
|
Chris@16
|
634 //!convertible, intersegment_ptrs will be convertibles. Never throws.
|
Chris@16
|
635 template<class T2>
|
Chris@16
|
636 intersegment_ptr(const intersegment_ptr<T2> &ptr)
|
Chris@16
|
637 { pointer p(ptr.get()); (void)p; base_t::set_from_other(ptr); }
|
Chris@16
|
638
|
Chris@16
|
639 //!Emulates static_cast operator.
|
Chris@16
|
640 //!Never throws.
|
Chris@16
|
641 template<class U>
|
Chris@16
|
642 intersegment_ptr(const intersegment_ptr<U> &r, ipcdetail::static_cast_tag)
|
Chris@16
|
643 { base_t::set_from_pointer(static_cast<T*>(r.get())); }
|
Chris@16
|
644
|
Chris@16
|
645 //!Emulates const_cast operator.
|
Chris@16
|
646 //!Never throws.
|
Chris@16
|
647 template<class U>
|
Chris@16
|
648 intersegment_ptr(const intersegment_ptr<U> &r, ipcdetail::const_cast_tag)
|
Chris@16
|
649 { base_t::set_from_pointer(const_cast<T*>(r.get())); }
|
Chris@16
|
650
|
Chris@16
|
651 //!Emulates dynamic_cast operator.
|
Chris@16
|
652 //!Never throws.
|
Chris@16
|
653 template<class U>
|
Chris@16
|
654 intersegment_ptr(const intersegment_ptr<U> &r, ipcdetail::dynamic_cast_tag)
|
Chris@16
|
655 { base_t::set_from_pointer(dynamic_cast<T*>(r.get())); }
|
Chris@16
|
656
|
Chris@16
|
657 //!Emulates reinterpret_cast operator.
|
Chris@16
|
658 //!Never throws.
|
Chris@16
|
659 template<class U>
|
Chris@16
|
660 intersegment_ptr(const intersegment_ptr<U> &r, ipcdetail::reinterpret_cast_tag)
|
Chris@16
|
661 { base_t::set_from_pointer(reinterpret_cast<T*>(r.get())); }
|
Chris@16
|
662
|
Chris@16
|
663 //!Obtains raw pointer from offset.
|
Chris@16
|
664 //!Never throws.
|
Chris@16
|
665 pointer get()const
|
Chris@16
|
666 { return static_cast<pointer>(base_t::to_raw_pointer()); }
|
Chris@16
|
667
|
Chris@16
|
668 //!Pointer-like -> operator. It can return 0 pointer.
|
Chris@16
|
669 //!Never throws.
|
Chris@16
|
670 pointer operator->() const
|
Chris@16
|
671 { return self_t::get(); }
|
Chris@16
|
672
|
Chris@16
|
673 //!Dereferencing operator, if it is a null intersegment_ptr behavior
|
Chris@16
|
674 //!is undefined. Never throws.
|
Chris@16
|
675 reference operator* () const
|
Chris@16
|
676 { return *(self_t::get()); }
|
Chris@16
|
677
|
Chris@16
|
678 //!Indexing operator.
|
Chris@16
|
679 //!Never throws.
|
Chris@16
|
680 reference operator[](std::ptrdiff_t idx) const
|
Chris@16
|
681 { return self_t::get()[idx]; }
|
Chris@16
|
682
|
Chris@16
|
683 //!Assignment from pointer (saves extra conversion).
|
Chris@16
|
684 //!Never throws.
|
Chris@16
|
685 intersegment_ptr& operator= (pointer from)
|
Chris@16
|
686 { base_t::set_from_pointer(from); return *this; }
|
Chris@16
|
687
|
Chris@16
|
688 //!Assignment from other intersegment_ptr.
|
Chris@16
|
689 //!Never throws.
|
Chris@16
|
690 intersegment_ptr& operator= (const intersegment_ptr &ptr)
|
Chris@16
|
691 { base_t::set_from_other(ptr); return *this; }
|
Chris@16
|
692
|
Chris@16
|
693 //!Assignment from related intersegment_ptr. If pointers of pointee types
|
Chris@16
|
694 //!are assignable, intersegment_ptrs will be assignable. Never throws.
|
Chris@16
|
695 template <class T2>
|
Chris@16
|
696 intersegment_ptr& operator= (const intersegment_ptr<T2> & ptr)
|
Chris@16
|
697 {
|
Chris@16
|
698 pointer p(ptr.get()); (void)p;
|
Chris@16
|
699 base_t::set_from_other(ptr); return *this;
|
Chris@16
|
700 }
|
Chris@16
|
701
|
Chris@16
|
702 //!intersegment_ptr + std::ptrdiff_t.
|
Chris@16
|
703 //!Never throws.
|
Chris@16
|
704 intersegment_ptr operator+ (std::ptrdiff_t idx) const
|
Chris@16
|
705 {
|
Chris@16
|
706 intersegment_ptr result (*this);
|
Chris@16
|
707 result.inc_offset(idx*sizeof(T));
|
Chris@16
|
708 return result;
|
Chris@16
|
709 }
|
Chris@16
|
710
|
Chris@16
|
711 //!intersegment_ptr - std::ptrdiff_t.
|
Chris@16
|
712 //!Never throws.
|
Chris@16
|
713 intersegment_ptr operator- (std::ptrdiff_t idx) const
|
Chris@16
|
714 {
|
Chris@16
|
715 intersegment_ptr result (*this);
|
Chris@16
|
716 result.dec_offset(idx*sizeof(T));
|
Chris@16
|
717 return result;
|
Chris@16
|
718 }
|
Chris@16
|
719
|
Chris@16
|
720 //!intersegment_ptr += std::ptrdiff_t.
|
Chris@16
|
721 //!Never throws.
|
Chris@16
|
722 intersegment_ptr &operator+= (std::ptrdiff_t offset)
|
Chris@16
|
723 { base_t::inc_offset(offset*sizeof(T)); return *this; }
|
Chris@16
|
724
|
Chris@16
|
725 //!intersegment_ptr -= std::ptrdiff_t.
|
Chris@16
|
726 //!Never throws.
|
Chris@16
|
727 intersegment_ptr &operator-= (std::ptrdiff_t offset)
|
Chris@16
|
728 { base_t::dec_offset(offset*sizeof(T)); return *this; }
|
Chris@16
|
729
|
Chris@16
|
730 //!++intersegment_ptr.
|
Chris@16
|
731 //!Never throws.
|
Chris@16
|
732 intersegment_ptr& operator++ (void)
|
Chris@16
|
733 { base_t::inc_offset(sizeof(T)); return *this; }
|
Chris@16
|
734
|
Chris@16
|
735 //!intersegment_ptr++.
|
Chris@16
|
736 //!Never throws.
|
Chris@16
|
737 intersegment_ptr operator++ (int)
|
Chris@16
|
738 { intersegment_ptr temp(*this); ++*this; return temp; }
|
Chris@16
|
739
|
Chris@16
|
740 //!--intersegment_ptr.
|
Chris@16
|
741 //!Never throws.
|
Chris@16
|
742 intersegment_ptr& operator-- (void)
|
Chris@16
|
743 { base_t::dec_offset(sizeof(T)); return *this; }
|
Chris@16
|
744
|
Chris@16
|
745 //!intersegment_ptr--.
|
Chris@16
|
746 //!Never throws.
|
Chris@16
|
747 intersegment_ptr operator-- (int)
|
Chris@16
|
748 { intersegment_ptr temp(*this); --*this; return temp; }
|
Chris@16
|
749
|
Chris@16
|
750 //!Safe bool conversion operator.
|
Chris@16
|
751 //!Never throws.
|
Chris@16
|
752 operator unspecified_bool_type() const
|
Chris@16
|
753 { return base_t::is_null()? 0 : &self_t::unspecified_bool_type_func; }
|
Chris@16
|
754
|
Chris@16
|
755 //!Not operator. Not needed in theory, but improves portability.
|
Chris@16
|
756 //!Never throws.
|
Chris@16
|
757 bool operator! () const
|
Chris@16
|
758 { return base_t::is_null(); }
|
Chris@16
|
759
|
Chris@101
|
760 //!Swaps two intersegment_ptr-s. More efficient than standard swap.
|
Chris@16
|
761 //!Never throws.
|
Chris@16
|
762 void swap(intersegment_ptr &other)
|
Chris@16
|
763 { base_t::swap(other); }
|
Chris@16
|
764
|
Chris@16
|
765 //!Calculates the distance between two intersegment_ptr-s.
|
Chris@16
|
766 //!This only works with two basic_intersegment_ptr pointing
|
Chris@16
|
767 //!to the same segment. Otherwise undefined
|
Chris@16
|
768 template <class T2>
|
Chris@16
|
769 std::ptrdiff_t _diff(const intersegment_ptr<T2> &other) const
|
Chris@16
|
770 { return base_t::diff(other); }
|
Chris@16
|
771
|
Chris@16
|
772 //!Returns true if both point to the
|
Chris@16
|
773 //!same object
|
Chris@16
|
774 template <class T2>
|
Chris@16
|
775 bool _equal(const intersegment_ptr<T2>&other) const
|
Chris@16
|
776 { return base_t::equal(other); }
|
Chris@16
|
777
|
Chris@16
|
778 //!Returns true if *this is less than other.
|
Chris@16
|
779 //!This only works with two basic_intersegment_ptr pointing
|
Chris@16
|
780 //!to the same segment group. Otherwise undefined. Never throws
|
Chris@16
|
781 template <class T2>
|
Chris@16
|
782 bool _less(const intersegment_ptr<T2> &other) const
|
Chris@16
|
783 { return base_t::less(other); }
|
Chris@16
|
784 };
|
Chris@16
|
785
|
Chris@16
|
786 //!Compares the equality of two intersegment_ptr-s.
|
Chris@16
|
787 //!Never throws.
|
Chris@16
|
788 template <class T1, class T2> inline
|
Chris@16
|
789 bool operator ==(const intersegment_ptr<T1> &left,
|
Chris@16
|
790 const intersegment_ptr<T2> &right)
|
Chris@16
|
791 {
|
Chris@16
|
792 //Make sure both pointers can be compared
|
Chris@16
|
793 bool e = typename intersegment_ptr<T1>::pointer(0) ==
|
Chris@16
|
794 typename intersegment_ptr<T2>::pointer(0);
|
Chris@16
|
795 (void)e;
|
Chris@16
|
796 return left._equal(right);
|
Chris@16
|
797 }
|
Chris@16
|
798
|
Chris@16
|
799 //!Returns true if *this is less than other.
|
Chris@16
|
800 //!This only works with two basic_intersegment_ptr pointing
|
Chris@16
|
801 //!to the same segment group. Otherwise undefined. Never throws
|
Chris@16
|
802 template <class T1, class T2> inline
|
Chris@16
|
803 bool operator <(const intersegment_ptr<T1> &left,
|
Chris@16
|
804 const intersegment_ptr<T2> &right)
|
Chris@16
|
805 {
|
Chris@16
|
806 //Make sure both pointers can be compared
|
Chris@16
|
807 bool e = typename intersegment_ptr<T1>::pointer(0) <
|
Chris@16
|
808 typename intersegment_ptr<T2>::pointer(0);
|
Chris@16
|
809 (void)e;
|
Chris@16
|
810 return left._less(right);
|
Chris@16
|
811 }
|
Chris@16
|
812
|
Chris@16
|
813 template<class T1, class T2> inline
|
Chris@16
|
814 bool operator!= (const intersegment_ptr<T1> &pt1,
|
Chris@16
|
815 const intersegment_ptr<T2> &pt2)
|
Chris@16
|
816 { return !(pt1 ==pt2); }
|
Chris@16
|
817
|
Chris@16
|
818 //!intersegment_ptr<T1> <= intersegment_ptr<T2>.
|
Chris@16
|
819 //!Never throws.
|
Chris@16
|
820 template<class T1, class T2> inline
|
Chris@16
|
821 bool operator<= (const intersegment_ptr<T1> &pt1,
|
Chris@16
|
822 const intersegment_ptr<T2> &pt2)
|
Chris@16
|
823 { return !(pt1 > pt2); }
|
Chris@16
|
824
|
Chris@16
|
825 //!intersegment_ptr<T1> > intersegment_ptr<T2>.
|
Chris@16
|
826 //!Never throws.
|
Chris@16
|
827 template<class T1, class T2> inline
|
Chris@16
|
828 bool operator> (const intersegment_ptr<T1> &pt1,
|
Chris@16
|
829 const intersegment_ptr<T2> &pt2)
|
Chris@16
|
830 { return (pt2 < pt1); }
|
Chris@16
|
831
|
Chris@16
|
832 //!intersegment_ptr<T1> >= intersegment_ptr<T2>.
|
Chris@16
|
833 //!Never throws.
|
Chris@16
|
834 template<class T1, class T2> inline
|
Chris@16
|
835 bool operator>= (const intersegment_ptr<T1> &pt1,
|
Chris@16
|
836 const intersegment_ptr<T2> &pt2)
|
Chris@16
|
837 { return !(pt1 < pt2); }
|
Chris@16
|
838
|
Chris@16
|
839 //!operator<<
|
Chris@16
|
840 template<class E, class T, class U> inline
|
Chris@16
|
841 std::basic_ostream<E, T> & operator<<
|
Chris@16
|
842 (std::basic_ostream<E, T> & os, const intersegment_ptr<U> & p)
|
Chris@16
|
843 { return os << p.get(); }
|
Chris@16
|
844
|
Chris@16
|
845 //!operator>>
|
Chris@16
|
846 template<class E, class T, class U> inline
|
Chris@16
|
847 std::basic_istream<E, T> & operator>>
|
Chris@16
|
848 (std::basic_istream<E, T> & os, intersegment_ptr<U> & p)
|
Chris@16
|
849 { U * tmp; return os >> tmp; p = tmp; }
|
Chris@16
|
850
|
Chris@16
|
851 //!std::ptrdiff_t + intersegment_ptr.
|
Chris@16
|
852 //!The result is another pointer of the same segment
|
Chris@16
|
853 template<class T> inline
|
Chris@16
|
854 intersegment_ptr<T> operator+
|
Chris@16
|
855 (std::ptrdiff_t diff, const intersegment_ptr<T>& right)
|
Chris@16
|
856 { return right + diff; }
|
Chris@16
|
857
|
Chris@16
|
858 //!intersegment_ptr - intersegment_ptr.
|
Chris@16
|
859 //!This only works with two intersegment_ptr-s that point to the
|
Chris@16
|
860 //!same segment
|
Chris@16
|
861 template <class T, class T2> inline
|
Chris@16
|
862 std::ptrdiff_t operator- (const intersegment_ptr<T> &pt,
|
Chris@16
|
863 const intersegment_ptr<T2> &pt2)
|
Chris@16
|
864 { return pt._diff(pt2)/sizeof(T); }
|
Chris@16
|
865
|
Chris@16
|
866 //! swap specialization
|
Chris@16
|
867 template<class T> inline
|
Chris@16
|
868 void swap (boost::interprocess::intersegment_ptr<T> &pt,
|
Chris@16
|
869 boost::interprocess::intersegment_ptr<T> &pt2)
|
Chris@16
|
870 { pt.swap(pt2); }
|
Chris@16
|
871
|
Chris@16
|
872 //!to_raw_pointer() enables boost::mem_fn to recognize intersegment_ptr.
|
Chris@16
|
873 //!Never throws.
|
Chris@16
|
874 template<class T> inline
|
Chris@16
|
875 T * to_raw_pointer(boost::interprocess::intersegment_ptr<T> const & p)
|
Chris@16
|
876 { return p.get(); }
|
Chris@16
|
877
|
Chris@16
|
878 //!Simulation of static_cast between pointers.
|
Chris@16
|
879 //!Never throws.
|
Chris@16
|
880 template<class T, class U> inline
|
Chris@16
|
881 boost::interprocess::intersegment_ptr<T> static_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r)
|
Chris@16
|
882 { return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::static_cast_tag()); }
|
Chris@16
|
883
|
Chris@16
|
884 //!Simulation of const_cast between pointers.
|
Chris@16
|
885 //!Never throws.
|
Chris@16
|
886 template<class T, class U> inline
|
Chris@16
|
887 boost::interprocess::intersegment_ptr<T> const_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r)
|
Chris@16
|
888 { return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::const_cast_tag()); }
|
Chris@16
|
889
|
Chris@16
|
890 //!Simulation of dynamic_cast between pointers.
|
Chris@16
|
891 //!Never throws.
|
Chris@16
|
892 template<class T, class U> inline
|
Chris@16
|
893 boost::interprocess::intersegment_ptr<T> dynamic_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r)
|
Chris@16
|
894 { return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::dynamic_cast_tag()); }
|
Chris@16
|
895
|
Chris@16
|
896 //!Simulation of reinterpret_cast between pointers.
|
Chris@16
|
897 //!Never throws.
|
Chris@16
|
898 template<class T, class U> inline
|
Chris@16
|
899 boost::interprocess::intersegment_ptr<T> reinterpret_pointer_cast(const boost::interprocess::intersegment_ptr<U> &r)
|
Chris@16
|
900 { return boost::interprocess::intersegment_ptr<T>(r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); }
|
Chris@16
|
901
|
Chris@16
|
902 //!Trait class to detect if an smart pointer has
|
Chris@16
|
903 //!multi-segment addressing capabilities.
|
Chris@16
|
904 template <class T>
|
Chris@16
|
905 struct is_multisegment_ptr
|
Chris@16
|
906 <boost::interprocess::intersegment_ptr<T> >
|
Chris@16
|
907 {
|
Chris@16
|
908 static const bool value = true;
|
Chris@16
|
909 };
|
Chris@16
|
910
|
Chris@16
|
911 } //namespace interprocess {
|
Chris@16
|
912
|
Chris@16
|
913 #if defined(_MSC_VER) && (_MSC_VER < 1400)
|
Chris@16
|
914 //!to_raw_pointer() enables boost::mem_fn to recognize intersegment_ptr.
|
Chris@16
|
915 //!Never throws.
|
Chris@16
|
916 template<class T> inline
|
Chris@16
|
917 T * to_raw_pointer(boost::interprocess::intersegment_ptr<T> const & p)
|
Chris@16
|
918 { return p.get(); }
|
Chris@16
|
919 #endif
|
Chris@16
|
920
|
Chris@16
|
921 //!has_trivial_constructor<> == true_type specialization
|
Chris@16
|
922 //!for optimizations
|
Chris@16
|
923 template <class T>
|
Chris@16
|
924 struct has_trivial_constructor
|
Chris@16
|
925 < boost::interprocess::intersegment_ptr<T> >
|
Chris@16
|
926 : public true_type{};
|
Chris@16
|
927
|
Chris@16
|
928 //!has_trivial_destructor<> == true_type specialization
|
Chris@16
|
929 //!for optimizations
|
Chris@16
|
930 template <class T>
|
Chris@16
|
931 struct has_trivial_destructor
|
Chris@16
|
932 < boost::interprocess::intersegment_ptr<T> >
|
Chris@16
|
933 : public true_type{};
|
Chris@16
|
934
|
Chris@16
|
935 } //namespace boost {
|
Chris@16
|
936
|
Chris@16
|
937 #if 0
|
Chris@16
|
938
|
Chris@16
|
939 //bits
|
Chris@16
|
940 //-> is_segmented
|
Chris@16
|
941 //-> is_relative
|
Chris@16
|
942 //-> is_in_stack
|
Chris@16
|
943 //-> is_pointee_outside
|
Chris@16
|
944
|
Chris@16
|
945 //Data
|
Chris@16
|
946
|
Chris@16
|
947
|
Chris@16
|
948
|
Chris@16
|
949
|
Chris@16
|
950 //segmented:
|
Chris@16
|
951 //
|
Chris@16
|
952 // std::size_t ctrl : CTRL_BITS;
|
Chris@16
|
953 // std::size_t segment : MAX_SEGMENT_BITS;
|
Chris@16
|
954 // std::size_t offset;
|
Chris@16
|
955
|
Chris@16
|
956 //RELATIVE_SIZE_BITS = SIZE_T_BITS -
|
Chris@16
|
957 // MAX_SEGMENT_BITS -
|
Chris@16
|
958 // CTRL_BITS 10 10
|
Chris@16
|
959 //MAX_SEGMENT_SIZE = SIZE_T_BITS - ALIGN_BITS 20 52
|
Chris@16
|
960
|
Chris@16
|
961 //SIZE_T_BITS - 1 - ALIGN_BITS 19 51
|
Chris@16
|
962 //POW_SIZE_BITS = upper_log2
|
Chris@16
|
963 // (SIZE_T_BITS - 1 - ALIGN_BITS) 5 6
|
Chris@16
|
964 //FRC_SIZE_BITS = SIZE_T_BITS - CTRL_BITS
|
Chris@16
|
965 // MAX_SEGMENT_SIZE_ALIGNBITS - POW_SIZE_BITS 6 5
|
Chris@16
|
966
|
Chris@16
|
967 //relative:
|
Chris@16
|
968 //
|
Chris@16
|
969 // std::size_t ctrl : CTRL_BITS; 2 2
|
Chris@16
|
970 // std::size_t size_pow : POW_SIZE_BITS 5 6
|
Chris@16
|
971 // std::size_t size_frc : FRC_SIZE_BITS; 6 5
|
Chris@16
|
972 // std::size_t start : MAX_SEGMENT_SIZE_ALIGNBITS;19 51
|
Chris@16
|
973 // std::ptrdiff_t distance : SIZE_T_BITS; 32 64
|
Chris@16
|
974
|
Chris@16
|
975 //direct:
|
Chris@16
|
976 //
|
Chris@16
|
977 // std::size_t ctrl : CTRL_BITS; 2 2
|
Chris@16
|
978 // std::size_t dummy : SIZE_T_BITS - CTRL_BITS 30 62
|
Chris@16
|
979 // void *addr : SIZE_T_BITS; 32 64
|
Chris@16
|
980
|
Chris@16
|
981 //32 bits systems:
|
Chris@16
|
982 //Page alignment: 2**12
|
Chris@16
|
983 //
|
Chris@16
|
984
|
Chris@16
|
985 //!Obtains the address pointed by the
|
Chris@16
|
986 //!object
|
Chris@16
|
987 void *to_raw_pointer() const
|
Chris@16
|
988 {
|
Chris@16
|
989 if(this->is_pointee_outside() || this->is_in_stack()){
|
Chris@16
|
990 return raw_address();
|
Chris@16
|
991 }
|
Chris@16
|
992 else if(this->is_relative()){
|
Chris@16
|
993 return (const_cast<char*>(reinterpret_cast<const char*>(this))) + this->relative_pointee_offset();
|
Chris@16
|
994 }
|
Chris@16
|
995 else{
|
Chris@16
|
996 group_manager *m = get_segment_group_manager(addr);
|
Chris@16
|
997 char *base = static_cast<char*>(m->get_id_address(this->segmented_id()));
|
Chris@16
|
998 return base + this->segmented_offset();
|
Chris@16
|
999 }
|
Chris@16
|
1000 }
|
Chris@16
|
1001
|
Chris@16
|
1002 void set_from_pointer(const void *ptr)
|
Chris@16
|
1003 {
|
Chris@16
|
1004 if(!ptr){
|
Chris@16
|
1005 this->set_pointee_outside();
|
Chris@16
|
1006 this->raw_address(ptr);
|
Chris@16
|
1007 }
|
Chris@16
|
1008 else if(this->is_in_stack()){
|
Chris@16
|
1009 this->raw_address(ptr);
|
Chris@16
|
1010 }
|
Chris@16
|
1011 else if(this->is_relative() &&
|
Chris@16
|
1012 ( (ptr >= this->relative_start())
|
Chris@16
|
1013 &&(ptr < this->relative_start() + this->relative_size()))
|
Chris@16
|
1014 ){
|
Chris@16
|
1015 this->relative_offset(ptr - this);
|
Chris@16
|
1016 }
|
Chris@16
|
1017 else{
|
Chris@16
|
1018 segment_info_t ptr_info = get_id_from_addr(ptr);
|
Chris@16
|
1019 segment_info_t this_info = get_id_from_addr(this);
|
Chris@16
|
1020 if(ptr_info.segment_group != this_info.segment_group){
|
Chris@16
|
1021 if(!ptr_info.segment_group){
|
Chris@16
|
1022 this->set_in_stack();
|
Chris@16
|
1023 }
|
Chris@16
|
1024 else{
|
Chris@16
|
1025 this->set_pointee_outside();
|
Chris@16
|
1026 }
|
Chris@16
|
1027 }
|
Chris@16
|
1028 else if(ptr_info.segment_id == this_info.segment_id){
|
Chris@16
|
1029 set_relative();
|
Chris@16
|
1030 this->relative_size (ptr_info.size);
|
Chris@16
|
1031 this->relative_offset(static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this));
|
Chris@16
|
1032 this->relative_start (ptr_info.base);
|
Chris@16
|
1033 }
|
Chris@16
|
1034 }
|
Chris@16
|
1035 }
|
Chris@16
|
1036
|
Chris@16
|
1037 void set_from_other(const self_t &other)
|
Chris@16
|
1038 { this->set_from_pointer(other.to_raw_pointer()); }
|
Chris@16
|
1039
|
Chris@16
|
1040 #endif
|
Chris@16
|
1041
|
Chris@16
|
1042 #include <boost/interprocess/detail/config_end.hpp>
|
Chris@16
|
1043
|
Chris@16
|
1044 #endif //#ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP
|