2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
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 <gtest/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"
42 class cxx11_atomic_func: public ::testing::Test
45 template <typename AtomicFlag>
46 void do_test_atomic_flag_mo( AtomicFlag& f, atomics::memory_order order )
48 atomics::memory_order mo_clear = convert_to_store_order(order);
50 f.clear( convert_to_store_order(order) );
52 for ( int i = 0; i < 5; ++i ) {
53 EXPECT_FALSE( atomics::atomic_flag_test_and_set_explicit( &f, order ));
54 EXPECT_TRUE( atomics::atomic_flag_test_and_set_explicit( &f, order ) );
55 atomics::atomic_flag_clear_explicit( &f, mo_clear );
56 atomics::atomic_flag_clear_explicit( &f, mo_clear );
60 template <typename AtomicFlag>
61 void do_test_atomic_flag( AtomicFlag& f )
65 for ( int i = 0; i < 5; ++i ) {
66 EXPECT_FALSE( atomics::atomic_flag_test_and_set( &f ));
67 EXPECT_TRUE( atomics::atomic_flag_test_and_set( &f ) );
68 atomics::atomic_flag_clear(&f);
69 atomics::atomic_flag_clear(&f);
72 do_test_atomic_flag_mo( f, atomics::memory_order_relaxed );
73 do_test_atomic_flag_mo( f, atomics::memory_order_acquire );
74 do_test_atomic_flag_mo( f, atomics::memory_order_release );
75 do_test_atomic_flag_mo( f, atomics::memory_order_acq_rel );
76 do_test_atomic_flag_mo( f, atomics::memory_order_seq_cst );
79 template <class Atomic, typename Integral>
80 void do_test_atomic_type(Atomic& a )
82 typedef Integral integral_type;
84 EXPECT_TRUE( atomics::atomic_is_lock_free( &a ) );
85 atomics::atomic_store( &a, (integral_type) 0 );
87 EXPECT_EQ( atomics::atomic_load( &a ), 0 );
89 for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
90 integral_type n = integral_type(42) << (nByte * 8);
91 EXPECT_EQ( atomics::atomic_exchange( &a, n ), (integral_type) 0 );
92 EXPECT_EQ( atomics::atomic_load( &a ), n );
93 EXPECT_EQ( atomics::atomic_exchange( &a, (integral_type) 0 ), n );
94 EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) 0 );
97 integral_type prev = atomics::atomic_load( &a );
98 for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
99 integral_type n = integral_type(42) << (nByte * 8);
100 integral_type expected = prev;
102 EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &expected, n));
103 EXPECT_EQ( expected, prev );
104 EXPECT_NE( expected, n );
105 EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &expected, n) );
106 EXPECT_EQ( expected, n );
109 EXPECT_EQ( atomics::atomic_load( &a ), n );
112 atomics::atomic_store( &a, (integral_type) 0 );
114 prev = atomics::atomic_load( &a );
115 for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
116 integral_type n = integral_type(42) << (nByte * 8);
117 integral_type expected = prev;
119 EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &expected, n));
120 EXPECT_EQ( expected, prev );
121 EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &expected, n));
122 EXPECT_EQ( expected, n );
125 EXPECT_EQ( atomics::atomic_load( &a ), n );
128 EXPECT_EQ( atomics::atomic_exchange( &a, (integral_type) 0 ), prev );
131 template <class Atomic, typename Integral>
132 void do_test_atomic_integral( Atomic& a )
134 do_test_atomic_type< Atomic, Integral >( a );
136 typedef Integral integral_type;
139 atomics::atomic_store( &a, (integral_type) 0 );
142 for ( size_t nByte = 0; nByte < sizeof(integral_type); ++nByte )
144 integral_type prev = atomics::atomic_load( &a );
145 integral_type n = integral_type(42) << (nByte * 8);
147 EXPECT_EQ( atomics::atomic_fetch_add( &a, n ), prev );
151 for ( size_t nByte = sizeof(integral_type); nByte > 0; --nByte )
153 integral_type prev = atomics::atomic_load( &a );
154 integral_type n = integral_type(42) << ((nByte - 1) * 8);
156 EXPECT_EQ( atomics::atomic_fetch_sub( &a, n ), prev );
158 EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) 0 );
160 // fetch_or / fetc_xor / fetch_and
161 for ( size_t nBit = 0; nBit < sizeof(integral_type) * 8; ++nBit )
163 integral_type prev = atomics::atomic_load( &a );
164 integral_type mask = integral_type(1) << nBit;
166 EXPECT_EQ( atomics::atomic_fetch_or( &a, mask ), prev );
167 prev = atomics::atomic_load( &a );
168 EXPECT_EQ( ( prev & mask ), mask );
170 EXPECT_EQ( atomics::atomic_fetch_and( &a, (integral_type) ~mask ), prev );
171 prev = atomics::atomic_load( &a );
172 EXPECT_EQ( integral_type(prev & mask), integral_type(0));
174 EXPECT_EQ( atomics::atomic_fetch_xor( &a, mask ), prev );
175 prev = atomics::atomic_load( &a );
176 EXPECT_EQ( ( prev & mask), mask);
178 EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) -1 );
181 template <class Atomic, typename Integral>
182 void do_test_atomic_type( Atomic& a, atomics::memory_order order )
184 typedef Integral integral_type;
186 const atomics::memory_order oLoad = convert_to_load_order( order );
187 const atomics::memory_order oStore = convert_to_store_order( order );
189 EXPECT_TRUE( atomics::atomic_is_lock_free( &a ) );
190 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 = 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 = 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 = 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 = 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 = 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 ), 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 = 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), 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_TRUE( atomics::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_TRUE( atomics::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[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 )
491 atomics::memory_order oLoad = convert_to_load_order(order);
492 atomics::memory_order oStore = convert_to_store_order(order);
495 atomics::atomic_store_explicit( &a, (void *) arr, oStore );
496 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), 1 );
499 EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, (void **) &p, (void *)(arr + 5), order, atomics::memory_order_relaxed ));
500 EXPECT_EQ( p, arr + 0 );
502 EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, (void **) &p, (void *)(arr + 3), order, atomics::memory_order_relaxed ));
503 EXPECT_EQ( p, arr + 5 );
506 EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, (void **) &p, (void *)(arr + 3), order, atomics::memory_order_relaxed ));
507 EXPECT_EQ( p, arr + 5 );
509 EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, (void **) &p, (void *)(arr + 5), order, atomics::memory_order_relaxed ));
510 EXPECT_EQ( p, arr + 3 );
513 EXPECT_EQ( reinterpret_cast<char *>(atomics::atomic_exchange_explicit( &a, (void *) arr, order )), arr + 3 );
514 EXPECT_EQ( reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), arr );
515 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), 1 );
517 for ( char i = 1; i < aSize; ++i ) {
518 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), i );
519 atomics::atomic_fetch_add_explicit( &a, 1, order );
520 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), i + 1 );
523 for ( char i = aSize; i > 1; --i ) {
524 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), i );
525 atomics::atomic_fetch_sub_explicit( &a, 1, order );
526 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), i - 1 );
530 template <bool Volatile>
531 void do_test_atomic_pointer_void()
533 typedef typename add_volatile<atomics::atomic< void *>, Volatile>::type atomic_pointer;
536 const char aSize = sizeof(arr)/sizeof(arr[0]);
537 for ( char i = 0; i < aSize; ++i ) {
538 arr[unsigned(i)] = i + 1;
544 atomics::atomic_store( &a, (void *) arr );
545 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), 1 );
548 EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, (void **) &p, (void *)(arr + 5) ));
549 EXPECT_EQ( p, arr + 0 );
550 EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, (void **) &p, (void *)(arr + 3) ));
551 EXPECT_EQ( p, arr + 5 );
553 EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, (void **) &p, (void *)(arr + 3) ));
554 EXPECT_EQ( p, arr + 5 );
555 EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, (void **) &p, (void *)(arr + 5) ));
556 EXPECT_EQ( p, arr + 3 );
558 EXPECT_EQ( reinterpret_cast<char *>( atomics::atomic_exchange( &a, (void *) arr )), arr + 3 );
559 EXPECT_EQ( reinterpret_cast<char *>( atomics::atomic_load( &a )), arr );
560 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), 1 );
562 for ( char i = 1; i < aSize; ++i ) {
563 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), i );
564 atomics::atomic_fetch_add( &a, 1 );
565 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), i + 1 );
568 for ( char i = aSize; i > 1; --i ) {
569 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), i );
570 atomics::atomic_fetch_sub( &a, 1 );
571 EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), i - 1 );
574 do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_relaxed );
575 do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_acquire );
576 do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_release );
577 do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_acq_rel );
578 do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_seq_cst );
582 void test_atomic_flag()
584 atomics::atomic_flag flags[8];
585 for ( size_t i = 0; i < sizeof(flags)/sizeof(flags[0]); ++i )
586 do_test_atomic_flag( flags[i] );
588 void test_atomic_flag_volatile()
590 atomics::atomic_flag volatile flags[8];
591 for ( size_t i = 0; i < sizeof(flags)/sizeof(flags[0]); ++i )
592 do_test_atomic_flag( flags[i] );
595 template <typename AtomicBool>
596 void test_atomic_bool_()
599 for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
600 do_test_atomic_bool( a[i] );
602 do_test_atomic_bool( a[i], atomics::memory_order_relaxed );
603 do_test_atomic_bool( a[i], atomics::memory_order_acquire );
604 do_test_atomic_bool( a[i], atomics::memory_order_release );
605 do_test_atomic_bool( a[i], atomics::memory_order_acq_rel );
606 do_test_atomic_bool( a[i], atomics::memory_order_seq_cst );
610 void test_atomic_bool()
612 test_atomic_bool_<atomics::atomic<bool> >();
614 void test_atomic_bool_volatile()
616 test_atomic_bool_<atomics::atomic<bool> volatile >();
620 TEST_F( cxx11_atomic_func, atomic_char )
622 test_atomic_integral<char>();
624 TEST_F( cxx11_atomic_func, atomic_char_volatile )
626 test_atomic_integral_volatile<char>();
628 TEST_F( cxx11_atomic_func, atomic_unsigned_char )
630 test_atomic_integral<unsigned char>();
632 TEST_F( cxx11_atomic_func, atomic_unsigned_char_volatile )
634 test_atomic_integral_volatile<unsigned char>();
636 TEST_F( cxx11_atomic_func, atomic_signed_char )
638 test_atomic_integral<signed char>();
640 TEST_F( cxx11_atomic_func, atomic_signed_char_volatile )
642 test_atomic_integral_volatile<signed char>();
644 TEST_F( cxx11_atomic_func, atomic_short_int )
646 test_atomic_integral<short int>();
648 TEST_F( cxx11_atomic_func, atomic_short_int_volatile )
650 test_atomic_integral_volatile<short int>();
652 TEST_F( cxx11_atomic_func, atomic_unsigned_short_int )
654 test_atomic_integral<unsigned short int>();
656 TEST_F( cxx11_atomic_func, atomic_unsigned_short_int_volatile )
658 test_atomic_integral_volatile<unsigned short int>();
660 TEST_F( cxx11_atomic_func, atomic_int )
662 test_atomic_integral<int>();
664 TEST_F( cxx11_atomic_func, atomic_int_volatile )
666 test_atomic_integral_volatile<int>();
668 TEST_F( cxx11_atomic_func, atomic_unsigned_int )
670 test_atomic_integral<unsigned int>();
672 TEST_F( cxx11_atomic_func, atomic_unsigned_int_volatile )
674 test_atomic_integral_volatile<unsigned int>();
676 TEST_F( cxx11_atomic_func, atomic_long )
678 test_atomic_integral<long>();
680 TEST_F( cxx11_atomic_func, atomic_long_volatile )
682 test_atomic_integral_volatile<long>();
684 TEST_F( cxx11_atomic_func, atomic_unsigned_long )
686 test_atomic_integral<unsigned long>();
688 TEST_F( cxx11_atomic_func, atomic_unsigned_long_volatile )
690 test_atomic_integral_volatile<unsigned long>();
692 TEST_F( cxx11_atomic_func, atomic_long_long )
694 test_atomic_integral<long long>();
696 TEST_F( cxx11_atomic_func, atomic_long_long_volatile )
698 test_atomic_integral_volatile<long long>();
700 TEST_F( cxx11_atomic_func, atomic_unsigned_long_long )
702 test_atomic_integral<unsigned long long>();
704 TEST_F( cxx11_atomic_func, atomic_unsigned_long_long_volatile )
706 test_atomic_integral_volatile<unsigned long long>();
709 TEST_F( cxx11_atomic_func, atomic_pointer_void )
711 do_test_atomic_pointer_void<false>();
713 TEST_F( cxx11_atomic_func, atomic_pointer_void_volatile )
715 do_test_atomic_pointer_void<true>();
718 TEST_F( cxx11_atomic_func, atomic_pointer_char )
720 test_atomic_pointer_for<char, false>();
722 TEST_F( cxx11_atomic_func, atomic_pointer_char_volatile )
724 test_atomic_pointer_for<char, true>();
726 TEST_F( cxx11_atomic_func, atomic_pointer_short )
728 test_atomic_pointer_for<short, false>();
730 TEST_F( cxx11_atomic_func, atomic_pointer_short_volatile )
732 test_atomic_pointer_for<short, true>();
734 TEST_F( cxx11_atomic_func, atomic_pointer_int )
736 test_atomic_pointer_for<int, false>();
738 TEST_F( cxx11_atomic_func, atomic_pointer_int_volatile )
740 test_atomic_pointer_for<int, true>();
742 TEST_F( cxx11_atomic_func, atomic_pointer_long )
744 test_atomic_pointer_for<long, false>();
746 TEST_F( cxx11_atomic_func, atomic_pointer_long_volatile )
748 test_atomic_pointer_for<long, true>();
750 TEST_F( cxx11_atomic_func, atomic_pointer_long_long )
752 test_atomic_pointer_for<long long, false>();
754 TEST_F( cxx11_atomic_func, atomic_pointer_long_long_volatile )
756 test_atomic_pointer_for<long long, true>();
759 TEST_F( cxx11_atomic_func, test_atomic_fence )
761 atomics::atomic_thread_fence(atomics::memory_order_relaxed );
762 atomics::atomic_thread_fence(atomics::memory_order_acquire );
763 atomics::atomic_thread_fence(atomics::memory_order_release );
764 atomics::atomic_thread_fence(atomics::memory_order_acq_rel );
765 atomics::atomic_thread_fence(atomics::memory_order_seq_cst );
767 atomics::atomic_signal_fence(atomics::memory_order_relaxed );
768 atomics::atomic_signal_fence(atomics::memory_order_acquire );
769 atomics::atomic_signal_fence(atomics::memory_order_release );
770 atomics::atomic_signal_fence(atomics::memory_order_acq_rel );
771 atomics::atomic_signal_fence(atomics::memory_order_seq_cst );
776 #endif // #ifndef CDS_USE_BOOST_ATOMIC