2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <cds_test/ext_gtest.h>
32 #include <cds/algo/atomic.h>
34 #ifndef CDS_USE_BOOST_ATOMIC
35 // Skip this test for boost.atomic
36 // Boost.atomic has no free atomic functions implementation.
38 #include "cxx11_convert_memory_order.h"
40 #define EXPECT_ATOMIC_IS_LOCK_FREE( x ) EXPECT_TRUE( atomics::atomic_is_lock_free( &x ));
44 class cxx11_atomic_func: public ::testing::Test
47 template <typename AtomicFlag>
48 void do_test_atomic_flag_mo( AtomicFlag& f, atomics::memory_order order )
50 atomics::memory_order mo_clear = convert_to_store_order(order);
52 f.clear( convert_to_store_order(order));
54 for ( int i = 0; i < 5; ++i ) {
55 EXPECT_FALSE( atomics::atomic_flag_test_and_set_explicit( &f, order ));
56 EXPECT_TRUE( atomics::atomic_flag_test_and_set_explicit( &f, order ));
57 atomics::atomic_flag_clear_explicit( &f, mo_clear );
58 atomics::atomic_flag_clear_explicit( &f, mo_clear );
62 template <typename AtomicFlag>
63 void do_test_atomic_flag( AtomicFlag& f )
67 for ( int i = 0; i < 5; ++i ) {
68 EXPECT_FALSE( atomics::atomic_flag_test_and_set( &f ));
69 EXPECT_TRUE( atomics::atomic_flag_test_and_set( &f ));
70 atomics::atomic_flag_clear(&f);
71 atomics::atomic_flag_clear(&f);
74 do_test_atomic_flag_mo( f, atomics::memory_order_relaxed );
75 do_test_atomic_flag_mo( f, atomics::memory_order_acquire );
76 do_test_atomic_flag_mo( f, atomics::memory_order_release );
77 do_test_atomic_flag_mo( f, atomics::memory_order_acq_rel );
78 do_test_atomic_flag_mo( f, atomics::memory_order_seq_cst );
81 template <class Atomic, typename Integral>
82 void do_test_atomic_type(Atomic& a )
84 typedef Integral integral_type;
86 EXPECT_ATOMIC_IS_LOCK_FREE( a );
87 atomics::atomic_store( &a, (integral_type) 0 );
88 EXPECT_EQ( atomics::atomic_load( &a ), integral_type( 0 ));
90 for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
91 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
92 EXPECT_EQ( atomics::atomic_exchange( &a, n ), (integral_type) 0 );
93 EXPECT_EQ( atomics::atomic_load( &a ), n );
94 EXPECT_EQ( atomics::atomic_exchange( &a, (integral_type) 0 ), n );
95 EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) 0 );
98 integral_type prev = atomics::atomic_load( &a );
99 for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
100 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
101 integral_type expected = prev;
103 EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &expected, n));
104 EXPECT_EQ( expected, prev );
105 EXPECT_NE( expected, n );
106 EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &expected, n));
107 EXPECT_EQ( expected, n );
110 EXPECT_EQ( atomics::atomic_load( &a ), n );
113 atomics::atomic_store( &a, (integral_type) 0 );
115 prev = atomics::atomic_load( &a );
116 for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
117 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
118 integral_type expected = prev;
120 EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &expected, n));
121 EXPECT_EQ( expected, prev );
122 EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &expected, n));
123 EXPECT_EQ( expected, n );
126 EXPECT_EQ( atomics::atomic_load( &a ), n );
129 EXPECT_EQ( atomics::atomic_exchange( &a, (integral_type) 0 ), prev );
132 template <class Atomic, typename Integral>
133 void do_test_atomic_integral( Atomic& a )
135 do_test_atomic_type< Atomic, Integral >( a );
137 typedef Integral integral_type;
140 atomics::atomic_store( &a, (integral_type) 0 );
143 for ( size_t nByte = 0; nByte < sizeof(integral_type); ++nByte )
145 integral_type prev = atomics::atomic_load( &a );
146 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
148 EXPECT_EQ( atomics::atomic_fetch_add( &a, n ), prev );
152 for ( size_t nByte = sizeof(integral_type); nByte > 0; --nByte )
154 integral_type prev = atomics::atomic_load( &a );
155 integral_type n = static_cast<integral_type>( integral_type(42) << ((nByte - 1) * 8));
157 EXPECT_EQ( atomics::atomic_fetch_sub( &a, n ), prev );
159 EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) 0 );
161 // fetch_or / fetc_xor / fetch_and
162 for ( size_t nBit = 0; nBit < sizeof(integral_type) * 8; ++nBit )
164 integral_type prev = atomics::atomic_load( &a );
165 integral_type mask = static_cast<integral_type>( integral_type(1) << nBit );
167 EXPECT_EQ( atomics::atomic_fetch_or( &a, mask ), prev );
168 prev = atomics::atomic_load( &a );
169 EXPECT_EQ( ( prev & mask ), mask );
171 EXPECT_EQ( atomics::atomic_fetch_and( &a, (integral_type) ~mask ), prev );
172 prev = atomics::atomic_load( &a );
173 EXPECT_EQ( integral_type(prev & mask), integral_type(0));
175 EXPECT_EQ( atomics::atomic_fetch_xor( &a, mask ), prev );
176 prev = atomics::atomic_load( &a );
177 EXPECT_EQ( ( prev & mask), mask);
179 EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) -1 );
182 template <class Atomic, typename Integral>
183 void do_test_atomic_type( Atomic& a, atomics::memory_order order )
185 typedef Integral integral_type;
187 const atomics::memory_order oLoad = convert_to_load_order( order );
188 const atomics::memory_order oStore = convert_to_store_order( order );
190 EXPECT_ATOMIC_IS_LOCK_FREE( a );
191 atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
192 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) 0 );
194 for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
195 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
196 EXPECT_EQ( atomics::atomic_exchange_explicit( &a, n, order ), (integral_type) 0 );
197 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
198 EXPECT_EQ( atomics::atomic_exchange_explicit( &a, (integral_type) 0, order ), n );
199 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) 0 );
202 integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
203 for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
204 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
205 integral_type expected = prev;
207 EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
208 EXPECT_EQ( expected, prev );
209 EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
210 EXPECT_EQ( expected, n );
213 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
216 atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
218 prev = atomics::atomic_load_explicit( &a, oLoad );
219 for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
220 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
221 integral_type expected = prev;
223 EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
224 EXPECT_EQ( expected, prev );
225 EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
226 EXPECT_EQ( expected, n );
229 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
232 EXPECT_EQ( atomics::atomic_exchange_explicit( &a, (integral_type) 0, order ), prev );
235 template <class Atomic, typename Integral>
236 void do_test_atomic_integral( Atomic& a, atomics::memory_order order )
238 do_test_atomic_type< Atomic, Integral >( a, order );
239 typedef Integral integral_type;
241 const atomics::memory_order oLoad = convert_to_load_order( order );
242 const atomics::memory_order oStore = convert_to_store_order( order );
245 atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
248 for ( size_t nByte = 0; nByte < sizeof(integral_type); ++nByte )
250 integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
251 integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
253 EXPECT_EQ( atomics::atomic_fetch_add_explicit( &a, n, order), prev);
257 for ( size_t nByte = sizeof(integral_type); nByte > 0; --nByte )
259 integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
260 integral_type n = static_cast<integral_type>( integral_type(42) << ((nByte - 1) * 8));
262 EXPECT_EQ( atomics::atomic_fetch_sub_explicit( &a, n, order ), prev);
264 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), integral_type( 0 ));
266 // fetch_or / fetc_xor / fetch_and
267 for ( size_t nBit = 0; nBit < sizeof(integral_type) * 8; ++nBit )
269 integral_type prev = atomics::atomic_load_explicit( &a, oLoad ) ;;
270 integral_type mask = static_cast<integral_type>( integral_type(1) << nBit );
272 EXPECT_EQ( atomics::atomic_fetch_or_explicit( &a, mask, order ), prev );
273 prev = atomics::atomic_load_explicit( &a, oLoad );
274 EXPECT_EQ( ( prev & mask), mask);
276 EXPECT_EQ( atomics::atomic_fetch_and_explicit( &a, (integral_type) ~mask, order ), prev );
277 prev = atomics::atomic_load_explicit( &a, oLoad );
278 EXPECT_EQ( ( prev & mask), integral_type( 0 ));
280 EXPECT_EQ( atomics::atomic_fetch_xor_explicit( &a, mask, order ), prev );
281 prev = atomics::atomic_load_explicit( &a, oLoad );
282 EXPECT_EQ( ( prev & mask), mask);
284 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) -1 );
287 template <typename Atomic, typename Integral>
288 void test_atomic_integral_(Atomic& a)
290 do_test_atomic_integral<Atomic, Integral >(a);
292 do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_relaxed );
293 do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_acquire );
294 do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_release );
295 do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_acq_rel );
296 do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_seq_cst );
299 template <typename Integral>
300 void test_atomic_integral()
302 typedef atomics::atomic<Integral> atomic_type;
304 for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
305 test_atomic_integral_<atomic_type, Integral>( a[i] );
308 template <typename Integral>
309 void test_atomic_integral_volatile()
311 typedef atomics::atomic<Integral> volatile atomic_type;
313 for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
314 test_atomic_integral_<atomic_type, Integral>( a[i] );
318 template <class AtomicBool>
319 void do_test_atomic_bool(AtomicBool& a)
321 EXPECT_ATOMIC_IS_LOCK_FREE( a );
322 atomics::atomic_store( &a, false );
324 EXPECT_FALSE( atomics::atomic_load( &a ));
326 EXPECT_FALSE( atomics::atomic_exchange( &a, true ));
327 EXPECT_TRUE( atomics::atomic_load( &a ));
328 EXPECT_TRUE( atomics::atomic_exchange( &a, false ));
329 EXPECT_FALSE( atomics::atomic_load( &a ));
331 bool expected = false;
332 EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &expected, true));
333 EXPECT_FALSE( expected );
334 EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &expected, false));
335 EXPECT_TRUE( expected );
336 EXPECT_TRUE( atomics::atomic_load( &a ));
338 atomics::atomic_store( &a, false );
341 EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &expected, true));
342 EXPECT_FALSE( expected );
343 EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &expected, false));
344 EXPECT_TRUE( expected );
346 EXPECT_TRUE( atomics::atomic_load( &a ));
348 EXPECT_TRUE( atomics::atomic_exchange( &a, false ));
351 template <class AtomicBool>
352 void do_test_atomic_bool( AtomicBool& a, atomics::memory_order order )
354 const atomics::memory_order oLoad = convert_to_load_order( order );
355 const atomics::memory_order oStore = convert_to_store_order( order );
356 const atomics::memory_order oExchange = convert_to_exchange_order( order );
358 EXPECT_ATOMIC_IS_LOCK_FREE( a );
359 atomics::atomic_store_explicit( &a, false, oStore );
360 EXPECT_FALSE( a == false );
361 EXPECT_FALSE( atomics::atomic_load_explicit( &a, oLoad ));
363 EXPECT_FALSE( atomics::atomic_exchange_explicit( &a, true, oExchange ));
364 EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
365 EXPECT_TRUE( atomics::atomic_exchange_explicit( &a, false, oExchange ));
366 EXPECT_FALSE( atomics::atomic_load_explicit( &a, oLoad ));
368 bool expected = false;
369 EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, true, order, atomics::memory_order_relaxed));
370 EXPECT_FALSE( expected );
371 EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, false, order, atomics::memory_order_relaxed));
372 EXPECT_TRUE( expected );
373 EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
375 atomics::atomic_store( &a, false );
378 EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, true, order, atomics::memory_order_relaxed));
379 EXPECT_FALSE( expected );
380 EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, false, order, atomics::memory_order_relaxed));
381 EXPECT_TRUE( expected );
383 EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
385 EXPECT_TRUE( atomics::atomic_exchange_explicit( &a, false, oExchange ));
388 template <typename Atomic, typename Integral>
389 void test_atomic_pointer_for_( Atomic& a, Integral * arr, Integral aSize, atomics::memory_order order )
391 typedef Integral integral_type;
392 atomics::memory_order oLoad = convert_to_load_order(order);
393 atomics::memory_order oStore = convert_to_store_order(order);
396 atomics::atomic_store_explicit( &a, arr, oStore );
397 EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), 1 );
400 EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &p, arr + 5, order, atomics::memory_order_relaxed ));
401 EXPECT_EQ( p, arr + 0 );
403 EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &p, arr + 3, order, atomics::memory_order_relaxed ));
404 EXPECT_EQ( p, arr + 5 );
407 EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &p, arr + 3, order, atomics::memory_order_relaxed ));
408 EXPECT_EQ( p, arr + 5 );
410 EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &p, arr + 5, order, atomics::memory_order_relaxed ));
411 EXPECT_EQ( p, arr + 3 );
414 EXPECT_EQ( atomics::atomic_exchange_explicit( &a, arr, order ), arr + 3 );
415 EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), arr );
416 EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), 1 );
418 for ( integral_type i = 1; i < aSize; ++i ) {
419 integral_type * p = atomics::atomic_load_explicit( &a, oLoad );
421 EXPECT_EQ( atomics::atomic_fetch_add_explicit( &a, 1, order ), p );
422 EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), i + 1 );
425 for ( integral_type i = aSize; i > 1; --i ) {
426 integral_type * p = atomics::atomic_load_explicit( &a, oLoad );
428 EXPECT_EQ( atomics::atomic_fetch_sub_explicit( &a, 1, order ), p );
429 EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), i - 1 );
433 template <typename Integral, bool Volatile>
434 void test_atomic_pointer_for()
436 typedef Integral integral_type;
437 typedef typename add_volatile<atomics::atomic< integral_type *>, Volatile>::type atomic_pointer;
439 integral_type arr[8];
440 const integral_type aSize = sizeof(arr)/sizeof(arr[0]);
441 for ( integral_type i = 0; i < aSize; ++i ) {
442 arr[static_cast<size_t>(i)] = i + 1;
448 atomics::atomic_store( &a, arr );
449 EXPECT_EQ( *atomics::atomic_load( &a ), 1 );
452 EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &p, arr + 5 ));
453 EXPECT_EQ( p, arr + 0 );
454 EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &p, arr + 3 ));
455 EXPECT_EQ( p, arr + 5 );
457 EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &p, arr + 3 ));
458 EXPECT_EQ( p, arr + 5 );
459 EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &p, arr + 5 ));
460 EXPECT_EQ( p, arr + 3 );
462 EXPECT_EQ( atomics::atomic_exchange( &a, arr ), arr + 3 );
463 EXPECT_EQ( atomics::atomic_load( &a ), arr );
464 EXPECT_EQ( *atomics::atomic_load( &a ), 1 );
466 for ( integral_type i = 1; i < aSize; ++i ) {
467 integral_type * p = atomics::atomic_load( &a );
469 EXPECT_EQ( atomics::atomic_fetch_add( &a, 1 ), p );
470 EXPECT_EQ( *atomics::atomic_load( &a ), i + 1 );
473 for ( integral_type i = aSize; i > 1; --i ) {
474 integral_type * p = atomics::atomic_load( &a );
476 EXPECT_EQ( atomics::atomic_fetch_sub( &a, 1 ), p );
477 EXPECT_EQ( *atomics::atomic_load( &a ), i - 1 );
480 test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_relaxed );
481 test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_acquire );
482 test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_release );
483 test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_acq_rel );
484 test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_seq_cst );
488 template <typename Atomic>
489 void do_test_atomic_pointer_void_( Atomic& a, char * arr, char aSize, atomics::memory_order order )
493 atomics::memory_order oLoad = convert_to_load_order(order);
494 atomics::memory_order oStore = convert_to_store_order(order);
497 atomics::atomic_store_explicit( &a, (void *) arr, oStore );
498 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), 1 );
501 EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, (void **) &p, (void *)(arr + 5), order, atomics::memory_order_relaxed ));
502 EXPECT_EQ( p, arr + 0 );
504 EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, (void **) &p, (void *)(arr + 3), order, atomics::memory_order_relaxed ));
505 EXPECT_EQ( p, arr + 5 );
508 EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, (void **) &p, (void *)(arr + 3), order, atomics::memory_order_relaxed ));
509 EXPECT_EQ( p, arr + 5 );
511 EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, (void **) &p, (void *)(arr + 5), order, atomics::memory_order_relaxed ));
512 EXPECT_EQ( p, arr + 3 );
515 EXPECT_EQ( reinterpret_cast<char *>(atomics::atomic_exchange_explicit( &a, (void *) arr, order )), arr + 3 );
516 EXPECT_EQ( reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), arr );
517 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), 1 );
520 template <bool Volatile>
521 void do_test_atomic_pointer_void()
523 typedef typename add_volatile<atomics::atomic< void *>, Volatile>::type atomic_pointer;
526 const char aSize = sizeof(arr)/sizeof(arr[0]);
527 for ( char i = 0; i < aSize; ++i ) {
528 arr[static_cast<size_t>(i)] = i + 1;
534 atomics::atomic_store( &a, (void *) arr );
535 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), 1 );
538 EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, (void **) &p, (void *)(arr + 5)));
539 EXPECT_EQ( p, arr + 0 );
540 EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, (void **) &p, (void *)(arr + 3)));
541 EXPECT_EQ( p, arr + 5 );
543 EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, (void **) &p, (void *)(arr + 3)));
544 EXPECT_EQ( p, arr + 5 );
545 EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, (void **) &p, (void *)(arr + 5)));
546 EXPECT_EQ( p, arr + 3 );
548 EXPECT_EQ( reinterpret_cast<char *>( atomics::atomic_exchange( &a, (void *) arr )), arr + 3 );
549 EXPECT_EQ( reinterpret_cast<char *>( atomics::atomic_load( &a )), arr );
550 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), 1 );
552 do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_relaxed );
553 do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_acquire );
554 do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_release );
555 do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_acq_rel );
556 do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_seq_cst );
560 void test_atomic_flag()
562 atomics::atomic_flag flags[8];
563 for ( size_t i = 0; i < sizeof(flags)/sizeof(flags[0]); ++i )
564 do_test_atomic_flag( flags[i] );
566 void test_atomic_flag_volatile()
568 atomics::atomic_flag volatile flags[8];
569 for ( size_t i = 0; i < sizeof(flags)/sizeof(flags[0]); ++i )
570 do_test_atomic_flag( flags[i] );
573 template <typename AtomicBool>
574 void test_atomic_bool_()
577 for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
578 do_test_atomic_bool( a[i] );
580 do_test_atomic_bool( a[i], atomics::memory_order_relaxed );
581 do_test_atomic_bool( a[i], atomics::memory_order_acquire );
582 do_test_atomic_bool( a[i], atomics::memory_order_release );
583 do_test_atomic_bool( a[i], atomics::memory_order_acq_rel );
584 do_test_atomic_bool( a[i], atomics::memory_order_seq_cst );
588 void test_atomic_bool()
590 test_atomic_bool_<atomics::atomic<bool> >();
592 void test_atomic_bool_volatile()
594 test_atomic_bool_<atomics::atomic<bool> volatile >();
598 TEST_F( cxx11_atomic_func, atomic_char )
600 test_atomic_integral<char>();
602 TEST_F( cxx11_atomic_func, atomic_char_volatile )
604 test_atomic_integral_volatile<char>();
606 TEST_F( cxx11_atomic_func, atomic_unsigned_char )
608 test_atomic_integral<unsigned char>();
610 TEST_F( cxx11_atomic_func, atomic_unsigned_char_volatile )
612 test_atomic_integral_volatile<unsigned char>();
614 TEST_F( cxx11_atomic_func, atomic_signed_char )
616 test_atomic_integral<signed char>();
618 TEST_F( cxx11_atomic_func, atomic_signed_char_volatile )
620 test_atomic_integral_volatile<signed char>();
622 TEST_F( cxx11_atomic_func, atomic_short_int )
624 test_atomic_integral<short int>();
626 TEST_F( cxx11_atomic_func, atomic_short_int_volatile )
628 test_atomic_integral_volatile<short int>();
630 TEST_F( cxx11_atomic_func, atomic_unsigned_short_int )
632 test_atomic_integral<unsigned short int>();
634 TEST_F( cxx11_atomic_func, atomic_unsigned_short_int_volatile )
636 test_atomic_integral_volatile<unsigned short int>();
638 TEST_F( cxx11_atomic_func, atomic_int )
640 test_atomic_integral<int>();
642 TEST_F( cxx11_atomic_func, atomic_int_volatile )
644 test_atomic_integral_volatile<int>();
646 TEST_F( cxx11_atomic_func, atomic_unsigned_int )
648 test_atomic_integral<unsigned int>();
650 TEST_F( cxx11_atomic_func, atomic_unsigned_int_volatile )
652 test_atomic_integral_volatile<unsigned int>();
654 TEST_F( cxx11_atomic_func, atomic_long )
656 test_atomic_integral<long>();
658 TEST_F( cxx11_atomic_func, atomic_long_volatile )
660 test_atomic_integral_volatile<long>();
662 TEST_F( cxx11_atomic_func, atomic_unsigned_long )
664 test_atomic_integral<unsigned long>();
666 TEST_F( cxx11_atomic_func, atomic_unsigned_long_volatile )
668 test_atomic_integral_volatile<unsigned long>();
670 TEST_F( cxx11_atomic_func, atomic_long_long )
672 test_atomic_integral<long long>();
674 TEST_F( cxx11_atomic_func, atomic_long_long_volatile )
676 test_atomic_integral_volatile<long long>();
678 TEST_F( cxx11_atomic_func, atomic_unsigned_long_long )
680 test_atomic_integral<unsigned long long>();
682 TEST_F( cxx11_atomic_func, atomic_unsigned_long_long_volatile )
684 test_atomic_integral_volatile<unsigned long long>();
687 TEST_F( cxx11_atomic_func, atomic_pointer_void )
689 do_test_atomic_pointer_void<false>();
691 TEST_F( cxx11_atomic_func, atomic_pointer_void_volatile )
693 do_test_atomic_pointer_void<true>();
696 TEST_F( cxx11_atomic_func, atomic_pointer_char )
698 test_atomic_pointer_for<char, false>();
700 TEST_F( cxx11_atomic_func, atomic_pointer_char_volatile )
702 test_atomic_pointer_for<char, true>();
704 TEST_F( cxx11_atomic_func, atomic_pointer_short )
706 test_atomic_pointer_for<short, false>();
708 TEST_F( cxx11_atomic_func, atomic_pointer_short_volatile )
710 test_atomic_pointer_for<short, true>();
712 TEST_F( cxx11_atomic_func, atomic_pointer_int )
714 test_atomic_pointer_for<int, false>();
716 TEST_F( cxx11_atomic_func, atomic_pointer_int_volatile )
718 test_atomic_pointer_for<int, true>();
720 TEST_F( cxx11_atomic_func, atomic_pointer_long )
722 test_atomic_pointer_for<long, false>();
724 TEST_F( cxx11_atomic_func, atomic_pointer_long_volatile )
726 test_atomic_pointer_for<long, true>();
728 TEST_F( cxx11_atomic_func, atomic_pointer_long_long )
730 test_atomic_pointer_for<long long, false>();
732 TEST_F( cxx11_atomic_func, atomic_pointer_long_long_volatile )
734 test_atomic_pointer_for<long long, true>();
737 TEST_F( cxx11_atomic_func, test_atomic_fence )
739 atomics::atomic_thread_fence(atomics::memory_order_relaxed );
740 atomics::atomic_thread_fence(atomics::memory_order_acquire );
741 atomics::atomic_thread_fence(atomics::memory_order_release );
742 atomics::atomic_thread_fence(atomics::memory_order_acq_rel );
743 atomics::atomic_thread_fence(atomics::memory_order_seq_cst );
745 atomics::atomic_signal_fence(atomics::memory_order_relaxed );
746 atomics::atomic_signal_fence(atomics::memory_order_acquire );
747 atomics::atomic_signal_fence(atomics::memory_order_release );
748 atomics::atomic_signal_fence(atomics::memory_order_acq_rel );
749 atomics::atomic_signal_fence(atomics::memory_order_seq_cst );
754 #endif // #ifndef CDS_USE_BOOST_ATOMIC