Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/interprocess/detail/atomic.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 2006-2012 | |
4 // (C) Copyright Markus Schoepflin 2007 | |
5 // (C) Copyright Bryce Lelbach 2010 | |
6 // | |
7 // Distributed under the Boost Software License, Version 1.0. (See | |
8 // accompanying file LICENSE_1_0.txt or copy at | |
9 // http://www.boost.org/LICENSE_1_0.txt) | |
10 // | |
11 // See http://www.boost.org/libs/interprocess for documentation. | |
12 // | |
13 ////////////////////////////////////////////////////////////////////////////// | |
14 | |
15 #ifndef BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP | |
16 #define BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP | |
17 | |
18 #include <boost/interprocess/detail/config_begin.hpp> | |
19 #include <boost/interprocess/detail/workaround.hpp> | |
20 #include <boost/cstdint.hpp> | |
21 | |
22 namespace boost{ | |
23 namespace interprocess{ | |
24 namespace ipcdetail{ | |
25 | |
26 //! Atomically increment an boost::uint32_t by 1 | |
27 //! "mem": pointer to the object | |
28 //! Returns the old value pointed to by mem | |
29 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem); | |
30 | |
31 //! Atomically read an boost::uint32_t from memory | |
32 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem); | |
33 | |
34 //! Atomically set an boost::uint32_t in memory | |
35 //! "mem": pointer to the object | |
36 //! "param": val value that the object will assume | |
37 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val); | |
38 | |
39 //! Compare an boost::uint32_t's value with "cmp". | |
40 //! If they are the same swap the value with "with" | |
41 //! "mem": pointer to the value | |
42 //! "with": what to swap it with | |
43 //! "cmp": the value to compare it to | |
44 //! Returns the old value of *mem | |
45 inline boost::uint32_t atomic_cas32 | |
46 (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp); | |
47 | |
48 } //namespace ipcdetail{ | |
49 } //namespace interprocess{ | |
50 } //namespace boost{ | |
51 | |
52 #if (defined BOOST_INTERPROCESS_WINDOWS) | |
53 | |
54 #include <boost/interprocess/detail/win32_api.hpp> | |
55 | |
56 namespace boost{ | |
57 namespace interprocess{ | |
58 namespace ipcdetail{ | |
59 | |
60 //! Atomically decrement an boost::uint32_t by 1 | |
61 //! "mem": pointer to the atomic value | |
62 //! Returns the old value pointed to by mem | |
63 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) | |
64 { return winapi::interlocked_decrement(reinterpret_cast<volatile long*>(mem)) + 1; } | |
65 | |
66 //! Atomically increment an apr_uint32_t by 1 | |
67 //! "mem": pointer to the object | |
68 //! Returns the old value pointed to by mem | |
69 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) | |
70 { return winapi::interlocked_increment(reinterpret_cast<volatile long*>(mem))-1; } | |
71 | |
72 //! Atomically read an boost::uint32_t from memory | |
73 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) | |
74 { return *mem; } | |
75 | |
76 //! Atomically set an boost::uint32_t in memory | |
77 //! "mem": pointer to the object | |
78 //! "param": val value that the object will assume | |
79 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) | |
80 { winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), val); } | |
81 | |
82 //! Compare an boost::uint32_t's value with "cmp". | |
83 //! If they are the same swap the value with "with" | |
84 //! "mem": pointer to the value | |
85 //! "with": what to swap it with | |
86 //! "cmp": the value to compare it to | |
87 //! Returns the old value of *mem | |
88 inline boost::uint32_t atomic_cas32 | |
89 (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) | |
90 { return winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), with, cmp); } | |
91 | |
92 } //namespace ipcdetail{ | |
93 } //namespace interprocess{ | |
94 } //namespace boost{ | |
95 | |
96 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) | |
97 | |
98 namespace boost { | |
99 namespace interprocess { | |
100 namespace ipcdetail{ | |
101 | |
102 //! Compare an boost::uint32_t's value with "cmp". | |
103 //! If they are the same swap the value with "with" | |
104 //! "mem": pointer to the value | |
105 //! "with" what to swap it with | |
106 //! "cmp": the value to compare it to | |
107 //! Returns the old value of *mem | |
108 inline boost::uint32_t atomic_cas32 | |
109 (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) | |
110 { | |
111 boost::uint32_t prev = cmp; | |
112 // This version by Mans Rullgard of Pathscale | |
113 __asm__ __volatile__ ( "lock\n\t" | |
114 "cmpxchg %2,%0" | |
115 : "+m"(*mem), "+a"(prev) | |
116 : "r"(with) | |
117 : "cc"); | |
118 | |
119 return prev; | |
120 } | |
121 | |
122 //! Atomically add 'val' to an boost::uint32_t | |
123 //! "mem": pointer to the object | |
124 //! "val": amount to add | |
125 //! Returns the old value pointed to by mem | |
126 inline boost::uint32_t atomic_add32 | |
127 (volatile boost::uint32_t *mem, boost::uint32_t val) | |
128 { | |
129 // int r = *pw; | |
130 // *mem += val; | |
131 // return r; | |
132 int r; | |
133 | |
134 asm volatile | |
135 ( | |
136 "lock\n\t" | |
137 "xadd %1, %0": | |
138 "+m"( *mem ), "=r"( r ): // outputs (%0, %1) | |
139 "1"( val ): // inputs (%2 == %1) | |
140 "memory", "cc" // clobbers | |
141 ); | |
142 | |
143 return r; | |
144 } | |
145 | |
146 //! Atomically increment an apr_uint32_t by 1 | |
147 //! "mem": pointer to the object | |
148 //! Returns the old value pointed to by mem | |
149 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) | |
150 { return atomic_add32(mem, 1); } | |
151 | |
152 //! Atomically decrement an boost::uint32_t by 1 | |
153 //! "mem": pointer to the atomic value | |
154 //! Returns the old value pointed to by mem | |
155 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) | |
156 { return atomic_add32(mem, (boost::uint32_t)-1); } | |
157 | |
158 //! Atomically read an boost::uint32_t from memory | |
159 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) | |
160 { return *mem; } | |
161 | |
162 //! Atomically set an boost::uint32_t in memory | |
163 //! "mem": pointer to the object | |
164 //! "param": val value that the object will assume | |
165 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) | |
166 { *mem = val; } | |
167 | |
168 } //namespace ipcdetail{ | |
169 } //namespace interprocess{ | |
170 } //namespace boost{ | |
171 | |
172 #elif defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__)) | |
173 | |
174 namespace boost { | |
175 namespace interprocess { | |
176 namespace ipcdetail{ | |
177 | |
178 //! Atomically add 'val' to an boost::uint32_t | |
179 //! "mem": pointer to the object | |
180 //! "val": amount to add | |
181 //! Returns the old value pointed to by mem | |
182 inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val) | |
183 { | |
184 boost::uint32_t prev, temp; | |
185 | |
186 asm volatile ("1:\n\t" | |
187 "lwarx %0,0,%2\n\t" | |
188 "add %1,%0,%3\n\t" | |
189 "stwcx. %1,0,%2\n\t" | |
190 "bne- 1b" | |
191 : "=&r" (prev), "=&r" (temp) | |
192 : "b" (mem), "r" (val) | |
193 : "cc", "memory"); | |
194 return prev; | |
195 } | |
196 | |
197 //! Compare an boost::uint32_t's value with "cmp". | |
198 //! If they are the same swap the value with "with" | |
199 //! "mem": pointer to the value | |
200 //! "with" what to swap it with | |
201 //! "cmp": the value to compare it to | |
202 //! Returns the old value of *mem | |
203 inline boost::uint32_t atomic_cas32 | |
204 (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) | |
205 { | |
206 boost::uint32_t prev; | |
207 | |
208 asm volatile ("1:\n\t" | |
209 "lwarx %0,0,%1\n\t" | |
210 "cmpw %0,%3\n\t" | |
211 "bne- 2f\n\t" | |
212 "stwcx. %2,0,%1\n\t" | |
213 "bne- 1b\n\t" | |
214 "2:" | |
215 : "=&r"(prev) | |
216 : "b" (mem), "r" (with), "r" (cmp) | |
217 : "cc", "memory"); | |
218 return prev; | |
219 } | |
220 | |
221 //! Atomically increment an apr_uint32_t by 1 | |
222 //! "mem": pointer to the object | |
223 //! Returns the old value pointed to by mem | |
224 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) | |
225 { return atomic_add32(mem, 1); } | |
226 | |
227 //! Atomically decrement an boost::uint32_t by 1 | |
228 //! "mem": pointer to the atomic value | |
229 //! Returns the old value pointed to by mem | |
230 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) | |
231 { return atomic_add32(mem, boost::uint32_t(-1u)); } | |
232 | |
233 //! Atomically read an boost::uint32_t from memory | |
234 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) | |
235 { return *mem; } | |
236 | |
237 //! Atomically set an boost::uint32_t in memory | |
238 //! "mem": pointer to the object | |
239 //! "param": val value that the object will assume | |
240 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) | |
241 { *mem = val; } | |
242 | |
243 } //namespace ipcdetail{ | |
244 } //namespace interprocess{ | |
245 } //namespace boost{ | |
246 | |
247 #elif (defined(sun) || defined(__sun)) | |
248 | |
249 #include <atomic.h> | |
250 | |
251 namespace boost{ | |
252 namespace interprocess{ | |
253 namespace ipcdetail{ | |
254 | |
255 //! Atomically add 'val' to an boost::uint32_t | |
256 //! "mem": pointer to the object | |
257 //! "val": amount to add | |
258 //! Returns the old value pointed to by mem | |
259 inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val) | |
260 { return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (int32_t)val) - val; } | |
261 | |
262 //! Compare an boost::uint32_t's value with "cmp". | |
263 //! If they are the same swap the value with "with" | |
264 //! "mem": pointer to the value | |
265 //! "with" what to swap it with | |
266 //! "cmp": the value to compare it to | |
267 //! Returns the old value of *mem | |
268 inline boost::uint32_t atomic_cas32 | |
269 (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) | |
270 { return atomic_cas_32(reinterpret_cast<volatile ::uint32_t*>(mem), cmp, with); } | |
271 | |
272 //! Atomically increment an apr_uint32_t by 1 | |
273 //! "mem": pointer to the object | |
274 //! Returns the old value pointed to by mem | |
275 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) | |
276 { return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), 1) - 1; } | |
277 | |
278 //! Atomically decrement an boost::uint32_t by 1 | |
279 //! "mem": pointer to the atomic value | |
280 //! Returns the old value pointed to by mem | |
281 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) | |
282 { return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (boost::uint32_t)-1) + 1; } | |
283 | |
284 //! Atomically read an boost::uint32_t from memory | |
285 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) | |
286 { return *mem; } | |
287 | |
288 //! Atomically set an boost::uint32_t in memory | |
289 //! "mem": pointer to the object | |
290 //! "param": val value that the object will assume | |
291 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) | |
292 { *mem = val; } | |
293 | |
294 } //namespace ipcdetail{ | |
295 } //namespace interprocess{ | |
296 } //namespace boost{ | |
297 | |
298 #elif defined(__osf__) && defined(__DECCXX) | |
299 | |
300 #include <machine/builtins.h> | |
301 #include <c_asm.h> | |
302 | |
303 namespace boost{ | |
304 namespace interprocess{ | |
305 namespace ipcdetail{ | |
306 | |
307 //! Atomically decrement a uint32_t by 1 | |
308 //! "mem": pointer to the atomic value | |
309 //! Returns the old value pointed to by mem | |
310 //! Acquire, memory barrier after decrement. | |
311 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) | |
312 { boost::uint32_t old_val = __ATOMIC_DECREMENT_LONG(mem); __MB(); return old_val; } | |
313 | |
314 //! Atomically increment a uint32_t by 1 | |
315 //! "mem": pointer to the object | |
316 //! Returns the old value pointed to by mem | |
317 //! Release, memory barrier before increment. | |
318 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) | |
319 { __MB(); return __ATOMIC_INCREMENT_LONG(mem); } | |
320 | |
321 // Rational for the implementation of the atomic read and write functions. | |
322 // | |
323 // 1. The Alpha Architecture Handbook requires that access to a byte, | |
324 // an aligned word, an aligned longword, or an aligned quadword is | |
325 // atomic. (See 'Alpha Architecture Handbook', version 4, chapter 5.2.2.) | |
326 // | |
327 // 2. The CXX User's Guide states that volatile quantities are accessed | |
328 // with single assembler instructions, and that a compilation error | |
329 // occurs when declaring a quantity as volatile which is not properly | |
330 // aligned. | |
331 | |
332 //! Atomically read an boost::uint32_t from memory | |
333 //! Acquire, memory barrier after load. | |
334 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) | |
335 { boost::uint32_t old_val = *mem; __MB(); return old_val; } | |
336 | |
337 //! Atomically set an boost::uint32_t in memory | |
338 //! "mem": pointer to the object | |
339 //! "param": val value that the object will assume | |
340 //! Release, memory barrier before store. | |
341 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) | |
342 { __MB(); *mem = val; } | |
343 | |
344 //! Compare an boost::uint32_t's value with "cmp". | |
345 //! If they are the same swap the value with "with" | |
346 //! "mem": pointer to the value | |
347 //! "with" what to swap it with | |
348 //! "cmp": the value to compare it to | |
349 //! Returns the old value of *mem | |
350 //! Memory barrier between load and store. | |
351 inline boost::uint32_t atomic_cas32( | |
352 volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) | |
353 { | |
354 // Note: | |
355 // | |
356 // Branch prediction prefers backward branches, and the Alpha Architecture | |
357 // Handbook explicitely states that the loop should not be implemented like | |
358 // it is below. (See chapter 4.2.5.) Therefore the code should probably look | |
359 // like this: | |
360 // | |
361 // return asm( | |
362 // "10: ldl_l %v0,(%a0) ;" | |
363 // " cmpeq %v0,%a2,%t0 ;" | |
364 // " beq %t0,20f ;" | |
365 // " mb ;" | |
366 // " mov %a1,%t0 ;" | |
367 // " stl_c %t0,(%a0) ;" | |
368 // " beq %t0,30f ;" | |
369 // "20: ret ;" | |
370 // "30: br 10b;", | |
371 // mem, with, cmp); | |
372 // | |
373 // But as the compiler always transforms this into the form where a backward | |
374 // branch is taken on failure, we can as well implement it in the straight | |
375 // forward form, as this is what it will end up in anyway. | |
376 | |
377 return asm( | |
378 "10: ldl_l %v0,(%a0) ;" // load prev value from mem and lock mem | |
379 " cmpeq %v0,%a2,%t0 ;" // compare with given value | |
380 " beq %t0,20f ;" // if not equal, we're done | |
381 " mb ;" // memory barrier | |
382 " mov %a1,%t0 ;" // load new value into scratch register | |
383 " stl_c %t0,(%a0) ;" // store new value to locked mem (overwriting scratch) | |
384 " beq %t0,10b ;" // store failed because lock has been stolen, retry | |
385 "20: ", | |
386 mem, with, cmp); | |
387 } | |
388 | |
389 } //namespace ipcdetail{ | |
390 } //namespace interprocess{ | |
391 } //namespace boost{ | |
392 | |
393 #elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) | |
394 | |
395 #include <builtins.h> | |
396 | |
397 namespace boost { | |
398 namespace interprocess { | |
399 namespace ipcdetail{ | |
400 | |
401 //first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting | |
402 //all the functions with casts | |
403 | |
404 //! From XLC documenation : | |
405 //! This function can be used with a subsequent stwcxu call to implement a | |
406 //! read-modify-write on a specified memory location. The two functions work | |
407 //! together to ensure that if the store is successfully performed, no other | |
408 //! processor or mechanism can modify the target doubleword between the time | |
409 //! lwarxu function is executed and the time the stwcxu functio ncompletes. | |
410 //! "mem" : pointer to the object | |
411 //! Returns the value at pointed to by mem | |
412 inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem) | |
413 { | |
414 return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem))); | |
415 } | |
416 | |
417 //! "mem" : pointer to the object | |
418 //! "val" : the value to store | |
419 //! Returns true if the update of mem is successful and false if it is | |
420 //!unsuccessful | |
421 inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val) | |
422 { | |
423 return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0); | |
424 } | |
425 | |
426 //! "mem": pointer to the object | |
427 //! "val": amount to add | |
428 //! Returns the old value pointed to by mem | |
429 inline boost::uint32_t atomic_add32 | |
430 (volatile boost::uint32_t *mem, boost::uint32_t val) | |
431 { | |
432 boost::uint32_t oldValue; | |
433 do | |
434 { | |
435 oldValue = lwarxu(mem); | |
436 }while (!stwcxu(mem, oldValue+val)); | |
437 return oldValue; | |
438 } | |
439 | |
440 //! Atomically increment an apr_uint32_t by 1 | |
441 //! "mem": pointer to the object | |
442 //! Returns the old value pointed to by mem | |
443 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) | |
444 { return atomic_add32(mem, 1); } | |
445 | |
446 //! Atomically decrement an boost::uint32_t by 1 | |
447 //! "mem": pointer to the atomic value | |
448 //! Returns the old value pointed to by mem | |
449 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) | |
450 { return atomic_add32(mem, (boost::uint32_t)-1); } | |
451 | |
452 //! Atomically read an boost::uint32_t from memory | |
453 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) | |
454 { return *mem; } | |
455 | |
456 //! Compare an boost::uint32_t's value with "cmp". | |
457 //! If they are the same swap the value with "with" | |
458 //! "mem": pointer to the value | |
459 //! "with" what to swap it with | |
460 //! "cmp": the value to compare it to | |
461 //! Returns the old value of *mem | |
462 inline boost::uint32_t atomic_cas32 | |
463 (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) | |
464 { | |
465 boost::uint32_t oldValue; | |
466 boost::uint32_t valueToStore; | |
467 do | |
468 { | |
469 oldValue = lwarxu(mem); | |
470 } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue)); | |
471 | |
472 return oldValue; | |
473 } | |
474 | |
475 //! Atomically set an boost::uint32_t in memory | |
476 //! "mem": pointer to the object | |
477 //! "param": val value that the object will assume | |
478 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) | |
479 { *mem = val; } | |
480 | |
481 } //namespace ipcdetail | |
482 } //namespace interprocess | |
483 } //namespace boost | |
484 | |
485 #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) | |
486 | |
487 namespace boost { | |
488 namespace interprocess { | |
489 namespace ipcdetail{ | |
490 | |
491 //! Atomically add 'val' to an boost::uint32_t | |
492 //! "mem": pointer to the object | |
493 //! "val": amount to add | |
494 //! Returns the old value pointed to by mem | |
495 inline boost::uint32_t atomic_add32 | |
496 (volatile boost::uint32_t *mem, boost::uint32_t val) | |
497 { return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val); } | |
498 | |
499 //! Atomically increment an apr_uint32_t by 1 | |
500 //! "mem": pointer to the object | |
501 //! Returns the old value pointed to by mem | |
502 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) | |
503 { return atomic_add32(mem, 1); } | |
504 | |
505 //! Atomically decrement an boost::uint32_t by 1 | |
506 //! "mem": pointer to the atomic value | |
507 //! Returns the old value pointed to by mem | |
508 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) | |
509 { return atomic_add32(mem, (boost::uint32_t)-1); } | |
510 | |
511 //! Atomically read an boost::uint32_t from memory | |
512 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) | |
513 { return *mem; } | |
514 | |
515 //! Compare an boost::uint32_t's value with "cmp". | |
516 //! If they are the same swap the value with "with" | |
517 //! "mem": pointer to the value | |
518 //! "with" what to swap it with | |
519 //! "cmp": the value to compare it to | |
520 //! Returns the old value of *mem | |
521 inline boost::uint32_t atomic_cas32 | |
522 (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) | |
523 { return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with); } | |
524 | |
525 //! Atomically set an boost::uint32_t in memory | |
526 //! "mem": pointer to the object | |
527 //! "param": val value that the object will assume | |
528 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) | |
529 { *mem = val; } | |
530 | |
531 } //namespace ipcdetail{ | |
532 } //namespace interprocess{ | |
533 } //namespace boost{ | |
534 | |
535 #else | |
536 | |
537 #error No atomic operations implemented for this platform, sorry! | |
538 | |
539 #endif | |
540 | |
541 namespace boost{ | |
542 namespace interprocess{ | |
543 namespace ipcdetail{ | |
544 | |
545 inline bool atomic_add_unless32 | |
546 (volatile boost::uint32_t *mem, boost::uint32_t value, boost::uint32_t unless_this) | |
547 { | |
548 boost::uint32_t old, c(atomic_read32(mem)); | |
549 while(c != unless_this && (old = atomic_cas32(mem, c + value, c)) != c){ | |
550 c = old; | |
551 } | |
552 return c != unless_this; | |
553 } | |
554 | |
555 } //namespace ipcdetail | |
556 } //namespace interprocess | |
557 } //namespace boost | |
558 | |
559 | |
560 #include <boost/interprocess/detail/config_end.hpp> | |
561 | |
562 #endif //BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP |