| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729 |
- // Copyright (c) 2006-2018 Maxim Khizhinsky
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
- #include <cds_test/ext_gtest.h>
- #include <cds/algo/atomic.h>
- #ifndef CDS_USE_BOOST_ATOMIC
- // Skip this test for boost.atomic
- // Boost.atomic has no free atomic functions implementation.
- #include "cxx11_convert_memory_order.h"
- #define EXPECT_ATOMIC_IS_LOCK_FREE( x ) EXPECT_TRUE( atomics::atomic_is_lock_free( &x ));
- namespace misc {
- class cxx11_atomic_func: public ::testing::Test
- {
- protected:
- template <typename AtomicFlag>
- void do_test_atomic_flag_mo( AtomicFlag& f, atomics::memory_order order )
- {
- atomics::memory_order mo_clear = convert_to_store_order(order);
- f.clear( convert_to_store_order(order));
- for ( int i = 0; i < 5; ++i ) {
- EXPECT_FALSE( atomics::atomic_flag_test_and_set_explicit( &f, order ));
- EXPECT_TRUE( atomics::atomic_flag_test_and_set_explicit( &f, order ));
- atomics::atomic_flag_clear_explicit( &f, mo_clear );
- atomics::atomic_flag_clear_explicit( &f, mo_clear );
- }
- }
- template <typename AtomicFlag>
- void do_test_atomic_flag( AtomicFlag& f )
- {
- f.clear();
- for ( int i = 0; i < 5; ++i ) {
- EXPECT_FALSE( atomics::atomic_flag_test_and_set( &f ));
- EXPECT_TRUE( atomics::atomic_flag_test_and_set( &f ));
- atomics::atomic_flag_clear(&f);
- atomics::atomic_flag_clear(&f);
- }
- do_test_atomic_flag_mo( f, atomics::memory_order_relaxed );
- do_test_atomic_flag_mo( f, atomics::memory_order_acquire );
- do_test_atomic_flag_mo( f, atomics::memory_order_release );
- do_test_atomic_flag_mo( f, atomics::memory_order_acq_rel );
- do_test_atomic_flag_mo( f, atomics::memory_order_seq_cst );
- }
- template <class Atomic, typename Integral>
- void do_test_atomic_type(Atomic& a )
- {
- typedef Integral integral_type;
- EXPECT_ATOMIC_IS_LOCK_FREE( a );
- atomics::atomic_store( &a, (integral_type) 0 );
- EXPECT_EQ( atomics::atomic_load( &a ), integral_type( 0 ));
- for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
- integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
- EXPECT_EQ( atomics::atomic_exchange( &a, n ), (integral_type) 0 );
- EXPECT_EQ( atomics::atomic_load( &a ), n );
- EXPECT_EQ( atomics::atomic_exchange( &a, (integral_type) 0 ), n );
- EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) 0 );
- }
- integral_type prev = atomics::atomic_load( &a );
- for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
- integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
- integral_type expected = prev;
- EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &expected, n));
- EXPECT_EQ( expected, prev );
- EXPECT_NE( expected, n );
- EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &expected, n));
- EXPECT_EQ( expected, n );
- prev = n;
- EXPECT_EQ( atomics::atomic_load( &a ), n );
- }
- atomics::atomic_store( &a, (integral_type) 0 );
- prev = atomics::atomic_load( &a );
- for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
- integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
- integral_type expected = prev;
- EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &expected, n));
- EXPECT_EQ( expected, prev );
- EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &expected, n));
- EXPECT_EQ( expected, n );
- prev = n;
- EXPECT_EQ( atomics::atomic_load( &a ), n );
- }
- EXPECT_EQ( atomics::atomic_exchange( &a, (integral_type) 0 ), prev );
- }
- template <class Atomic, typename Integral>
- void do_test_atomic_integral( Atomic& a )
- {
- do_test_atomic_type< Atomic, Integral >( a );
- typedef Integral integral_type;
- // fetch_xxx testing
- atomics::atomic_store( &a, (integral_type) 0 );
- // fetch_add
- for ( size_t nByte = 0; nByte < sizeof(integral_type); ++nByte )
- {
- integral_type prev = atomics::atomic_load( &a );
- integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
- EXPECT_EQ( atomics::atomic_fetch_add( &a, n ), prev );
- }
- // fetch_sub
- for ( size_t nByte = sizeof(integral_type); nByte > 0; --nByte )
- {
- integral_type prev = atomics::atomic_load( &a );
- integral_type n = static_cast<integral_type>( integral_type(42) << ((nByte - 1) * 8));
- EXPECT_EQ( atomics::atomic_fetch_sub( &a, n ), prev );
- }
- EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) 0 );
- // fetch_or / fetc_xor / fetch_and
- for ( size_t nBit = 0; nBit < sizeof(integral_type) * 8; ++nBit )
- {
- integral_type prev = atomics::atomic_load( &a );
- integral_type mask = static_cast<integral_type>( integral_type(1) << nBit );
- EXPECT_EQ( atomics::atomic_fetch_or( &a, mask ), prev );
- prev = atomics::atomic_load( &a );
- EXPECT_EQ( ( prev & mask ), mask );
- EXPECT_EQ( atomics::atomic_fetch_and( &a, (integral_type) ~mask ), prev );
- prev = atomics::atomic_load( &a );
- EXPECT_EQ( integral_type(prev & mask), integral_type(0));
- EXPECT_EQ( atomics::atomic_fetch_xor( &a, mask ), prev );
- prev = atomics::atomic_load( &a );
- EXPECT_EQ( ( prev & mask), mask);
- }
- EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) -1 );
- }
- template <class Atomic, typename Integral>
- void do_test_atomic_type( Atomic& a, atomics::memory_order order )
- {
- typedef Integral integral_type;
- const atomics::memory_order oLoad = convert_to_load_order( order );
- const atomics::memory_order oStore = convert_to_store_order( order );
- EXPECT_ATOMIC_IS_LOCK_FREE( a );
- atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
- EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) 0 );
- for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
- integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
- EXPECT_EQ( atomics::atomic_exchange_explicit( &a, n, order ), (integral_type) 0 );
- EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
- EXPECT_EQ( atomics::atomic_exchange_explicit( &a, (integral_type) 0, order ), n );
- EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) 0 );
- }
- integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
- for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
- integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
- integral_type expected = prev;
- EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
- EXPECT_EQ( expected, prev );
- EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
- EXPECT_EQ( expected, n );
- prev = n;
- EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
- }
- atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
- prev = atomics::atomic_load_explicit( &a, oLoad );
- for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
- integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
- integral_type expected = prev;
- EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
- EXPECT_EQ( expected, prev );
- EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
- EXPECT_EQ( expected, n );
- prev = n;
- EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
- }
- EXPECT_EQ( atomics::atomic_exchange_explicit( &a, (integral_type) 0, order ), prev );
- }
- template <class Atomic, typename Integral>
- void do_test_atomic_integral( Atomic& a, atomics::memory_order order )
- {
- do_test_atomic_type< Atomic, Integral >( a, order );
- typedef Integral integral_type;
- const atomics::memory_order oLoad = convert_to_load_order( order );
- const atomics::memory_order oStore = convert_to_store_order( order );
- // fetch_xxx testing
- atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
- // fetch_add
- for ( size_t nByte = 0; nByte < sizeof(integral_type); ++nByte )
- {
- integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
- integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
- EXPECT_EQ( atomics::atomic_fetch_add_explicit( &a, n, order), prev);
- }
- // fetch_sub
- for ( size_t nByte = sizeof(integral_type); nByte > 0; --nByte )
- {
- integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
- integral_type n = static_cast<integral_type>( integral_type(42) << ((nByte - 1) * 8));
- EXPECT_EQ( atomics::atomic_fetch_sub_explicit( &a, n, order ), prev);
- }
- EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), integral_type( 0 ));
- // fetch_or / fetc_xor / fetch_and
- for ( size_t nBit = 0; nBit < sizeof(integral_type) * 8; ++nBit )
- {
- integral_type prev = atomics::atomic_load_explicit( &a, oLoad ) ;;
- integral_type mask = static_cast<integral_type>( integral_type(1) << nBit );
- EXPECT_EQ( atomics::atomic_fetch_or_explicit( &a, mask, order ), prev );
- prev = atomics::atomic_load_explicit( &a, oLoad );
- EXPECT_EQ( ( prev & mask), mask);
- EXPECT_EQ( atomics::atomic_fetch_and_explicit( &a, (integral_type) ~mask, order ), prev );
- prev = atomics::atomic_load_explicit( &a, oLoad );
- EXPECT_EQ( ( prev & mask), integral_type( 0 ));
- EXPECT_EQ( atomics::atomic_fetch_xor_explicit( &a, mask, order ), prev );
- prev = atomics::atomic_load_explicit( &a, oLoad );
- EXPECT_EQ( ( prev & mask), mask);
- }
- EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) -1 );
- }
- template <typename Atomic, typename Integral>
- void test_atomic_integral_(Atomic& a)
- {
- do_test_atomic_integral<Atomic, Integral >(a);
- do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_relaxed );
- do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_acquire );
- do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_release );
- do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_acq_rel );
- do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_seq_cst );
- }
- template <typename Integral>
- void test_atomic_integral()
- {
- typedef atomics::atomic<Integral> atomic_type;
- atomic_type a[8];
- for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
- test_atomic_integral_<atomic_type, Integral>( a[i] );
- }
- }
- template <typename Integral>
- void test_atomic_integral_volatile()
- {
- typedef atomics::atomic<Integral> volatile atomic_type;
- atomic_type a[8];
- for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
- test_atomic_integral_<atomic_type, Integral>( a[i] );
- }
- }
- template <class AtomicBool>
- void do_test_atomic_bool(AtomicBool& a)
- {
- EXPECT_ATOMIC_IS_LOCK_FREE( a );
- atomics::atomic_store( &a, false );
- EXPECT_FALSE( a );
- EXPECT_FALSE( atomics::atomic_load( &a ));
- EXPECT_FALSE( atomics::atomic_exchange( &a, true ));
- EXPECT_TRUE( atomics::atomic_load( &a ));
- EXPECT_TRUE( atomics::atomic_exchange( &a, false ));
- EXPECT_FALSE( atomics::atomic_load( &a ));
- bool expected = false;
- EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &expected, true));
- EXPECT_FALSE( expected );
- EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &expected, false));
- EXPECT_TRUE( expected );
- EXPECT_TRUE( atomics::atomic_load( &a ));
- atomics::atomic_store( &a, false );
- expected = false;
- EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &expected, true));
- EXPECT_FALSE( expected );
- EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &expected, false));
- EXPECT_TRUE( expected );
- EXPECT_TRUE( atomics::atomic_load( &a ));
- EXPECT_TRUE( atomics::atomic_exchange( &a, false ));
- }
- template <class AtomicBool>
- void do_test_atomic_bool( AtomicBool& a, atomics::memory_order order )
- {
- const atomics::memory_order oLoad = convert_to_load_order( order );
- const atomics::memory_order oStore = convert_to_store_order( order );
- const atomics::memory_order oExchange = convert_to_exchange_order( order );
- EXPECT_ATOMIC_IS_LOCK_FREE( a );
- atomics::atomic_store_explicit( &a, false, oStore );
- EXPECT_FALSE( a == false );
- EXPECT_FALSE( atomics::atomic_load_explicit( &a, oLoad ));
- EXPECT_FALSE( atomics::atomic_exchange_explicit( &a, true, oExchange ));
- EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
- EXPECT_TRUE( atomics::atomic_exchange_explicit( &a, false, oExchange ));
- EXPECT_FALSE( atomics::atomic_load_explicit( &a, oLoad ));
- bool expected = false;
- EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, true, order, atomics::memory_order_relaxed));
- EXPECT_FALSE( expected );
- EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, false, order, atomics::memory_order_relaxed));
- EXPECT_TRUE( expected );
- EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
- atomics::atomic_store( &a, false );
- expected = false;
- EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, true, order, atomics::memory_order_relaxed));
- EXPECT_FALSE( expected );
- EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, false, order, atomics::memory_order_relaxed));
- EXPECT_TRUE( expected );
- EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
- EXPECT_TRUE( atomics::atomic_exchange_explicit( &a, false, oExchange ));
- }
- template <typename Atomic, typename Integral>
- void test_atomic_pointer_for_( Atomic& a, Integral * arr, Integral aSize, atomics::memory_order order )
- {
- typedef Integral integral_type;
- atomics::memory_order oLoad = convert_to_load_order(order);
- atomics::memory_order oStore = convert_to_store_order(order);
- integral_type * p;
- atomics::atomic_store_explicit( &a, arr, oStore );
- EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), 1 );
- p = arr;
- EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &p, arr + 5, order, atomics::memory_order_relaxed ));
- EXPECT_EQ( p, arr + 0 );
- EXPECT_EQ( *p, 1 );
- EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &p, arr + 3, order, atomics::memory_order_relaxed ));
- EXPECT_EQ( p, arr + 5 );
- EXPECT_EQ( *p, 6 );
- EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &p, arr + 3, order, atomics::memory_order_relaxed ));
- EXPECT_EQ( p, arr + 5 );
- EXPECT_EQ( *p, 6 );
- EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &p, arr + 5, order, atomics::memory_order_relaxed ));
- EXPECT_EQ( p, arr + 3 );
- EXPECT_EQ( *p, 4 );
- EXPECT_EQ( atomics::atomic_exchange_explicit( &a, arr, order ), arr + 3 );
- EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), arr );
- EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), 1 );
- for ( integral_type i = 1; i < aSize; ++i ) {
- p = atomics::atomic_load_explicit( &a, oLoad );
- EXPECT_EQ( *p, i );
- EXPECT_EQ( atomics::atomic_fetch_add_explicit( &a, 1, order ), p );
- EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), i + 1 );
- }
- for ( integral_type i = aSize; i > 1; --i ) {
- p = atomics::atomic_load_explicit( &a, oLoad );
- EXPECT_EQ( *p, i );
- EXPECT_EQ( atomics::atomic_fetch_sub_explicit( &a, 1, order ), p );
- EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), i - 1 );
- }
- }
- template <typename Integral, bool Volatile>
- void test_atomic_pointer_for()
- {
- typedef Integral integral_type;
- typedef typename add_volatile<atomics::atomic< integral_type *>, Volatile>::type atomic_pointer;
- integral_type arr[8];
- const integral_type aSize = sizeof(arr)/sizeof(arr[0]);
- for ( integral_type i = 0; i < aSize; ++i ) {
- arr[static_cast<size_t>(i)] = i + 1;
- }
- atomic_pointer a;
- integral_type * p;
- atomics::atomic_store( &a, arr );
- EXPECT_EQ( *atomics::atomic_load( &a ), 1 );
- p = arr;
- EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &p, arr + 5 ));
- EXPECT_EQ( p, arr + 0 );
- EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &p, arr + 3 ));
- EXPECT_EQ( p, arr + 5 );
- EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &p, arr + 3 ));
- EXPECT_EQ( p, arr + 5 );
- EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &p, arr + 5 ));
- EXPECT_EQ( p, arr + 3 );
- EXPECT_EQ( atomics::atomic_exchange( &a, arr ), arr + 3 );
- EXPECT_EQ( atomics::atomic_load( &a ), arr );
- EXPECT_EQ( *atomics::atomic_load( &a ), 1 );
- for ( integral_type i = 1; i < aSize; ++i ) {
- p = atomics::atomic_load( &a );
- EXPECT_EQ( *p, i );
- EXPECT_EQ( atomics::atomic_fetch_add( &a, 1 ), p );
- EXPECT_EQ( *atomics::atomic_load( &a ), i + 1 );
- }
- for ( integral_type i = aSize; i > 1; --i ) {
- p = atomics::atomic_load( &a );
- EXPECT_EQ( *p, i );
- EXPECT_EQ( atomics::atomic_fetch_sub( &a, 1 ), p );
- EXPECT_EQ( *atomics::atomic_load( &a ), i - 1 );
- }
- test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_relaxed );
- test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_acquire );
- test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_release );
- test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_acq_rel );
- test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_seq_cst );
- }
- template <typename Atomic>
- void do_test_atomic_pointer_void_( Atomic& a, char * arr, char aSize, atomics::memory_order order )
- {
- CDS_UNUSED( aSize );
- atomics::memory_order oLoad = convert_to_load_order(order);
- atomics::memory_order oStore = convert_to_store_order(order);
- char * p;
- atomics::atomic_store_explicit( &a, (void *) arr, oStore );
- EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), 1 );
- p = arr;
- EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, (void **) &p, (void *)(arr + 5), order, atomics::memory_order_relaxed ));
- EXPECT_EQ( p, arr + 0 );
- EXPECT_EQ( *p, 1 );
- EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, (void **) &p, (void *)(arr + 3), order, atomics::memory_order_relaxed ));
- EXPECT_EQ( p, arr + 5 );
- EXPECT_EQ( *p, 6 );
- EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, (void **) &p, (void *)(arr + 3), order, atomics::memory_order_relaxed ));
- EXPECT_EQ( p, arr + 5 );
- EXPECT_EQ( *p, 6 );
- EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, (void **) &p, (void *)(arr + 5), order, atomics::memory_order_relaxed ));
- EXPECT_EQ( p, arr + 3 );
- EXPECT_EQ( *p, 4 );
- EXPECT_EQ( reinterpret_cast<char *>(atomics::atomic_exchange_explicit( &a, (void *) arr, order )), arr + 3 );
- EXPECT_EQ( reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), arr );
- EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), 1 );
- }
- template <bool Volatile>
- void do_test_atomic_pointer_void()
- {
- typedef typename add_volatile<atomics::atomic< void *>, Volatile>::type atomic_pointer;
- char arr[8];
- const char aSize = sizeof(arr)/sizeof(arr[0]);
- for ( char i = 0; i < aSize; ++i ) {
- arr[static_cast<size_t>(i)] = i + 1;
- }
- atomic_pointer a;
- char * p;
- atomics::atomic_store( &a, (void *) arr );
- EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), 1 );
- p = arr;
- EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, (void **) &p, (void *)(arr + 5)));
- EXPECT_EQ( p, arr + 0 );
- EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, (void **) &p, (void *)(arr + 3)));
- EXPECT_EQ( p, arr + 5 );
- EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, (void **) &p, (void *)(arr + 3)));
- EXPECT_EQ( p, arr + 5 );
- EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, (void **) &p, (void *)(arr + 5)));
- EXPECT_EQ( p, arr + 3 );
- EXPECT_EQ( reinterpret_cast<char *>( atomics::atomic_exchange( &a, (void *) arr )), arr + 3 );
- EXPECT_EQ( reinterpret_cast<char *>( atomics::atomic_load( &a )), arr );
- EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), 1 );
- do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_relaxed );
- do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_acquire );
- do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_release );
- do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_acq_rel );
- do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_seq_cst );
- }
- public:
- void test_atomic_flag()
- {
- atomics::atomic_flag flags[8];
- for ( size_t i = 0; i < sizeof(flags)/sizeof(flags[0]); ++i )
- do_test_atomic_flag( flags[i] );
- }
- void test_atomic_flag_volatile()
- {
- atomics::atomic_flag volatile flags[8];
- for ( size_t i = 0; i < sizeof(flags)/sizeof(flags[0]); ++i )
- do_test_atomic_flag( flags[i] );
- }
- template <typename AtomicBool>
- void test_atomic_bool_()
- {
- AtomicBool a[8];
- for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
- do_test_atomic_bool( a[i] );
- do_test_atomic_bool( a[i], atomics::memory_order_relaxed );
- do_test_atomic_bool( a[i], atomics::memory_order_acquire );
- do_test_atomic_bool( a[i], atomics::memory_order_release );
- do_test_atomic_bool( a[i], atomics::memory_order_acq_rel );
- do_test_atomic_bool( a[i], atomics::memory_order_seq_cst );
- }
- }
- void test_atomic_bool()
- {
- test_atomic_bool_<atomics::atomic<bool> >();
- }
- void test_atomic_bool_volatile()
- {
- test_atomic_bool_<atomics::atomic<bool> volatile >();
- }
- };
- TEST_F( cxx11_atomic_func, atomic_char )
- {
- test_atomic_integral<char>();
- }
- TEST_F( cxx11_atomic_func, atomic_char_volatile )
- {
- test_atomic_integral_volatile<char>();
- }
- TEST_F( cxx11_atomic_func, atomic_unsigned_char )
- {
- test_atomic_integral<unsigned char>();
- }
- TEST_F( cxx11_atomic_func, atomic_unsigned_char_volatile )
- {
- test_atomic_integral_volatile<unsigned char>();
- }
- TEST_F( cxx11_atomic_func, atomic_signed_char )
- {
- test_atomic_integral<signed char>();
- }
- TEST_F( cxx11_atomic_func, atomic_signed_char_volatile )
- {
- test_atomic_integral_volatile<signed char>();
- }
- TEST_F( cxx11_atomic_func, atomic_short_int )
- {
- test_atomic_integral<short int>();
- }
- TEST_F( cxx11_atomic_func, atomic_short_int_volatile )
- {
- test_atomic_integral_volatile<short int>();
- }
- TEST_F( cxx11_atomic_func, atomic_unsigned_short_int )
- {
- test_atomic_integral<unsigned short int>();
- }
- TEST_F( cxx11_atomic_func, atomic_unsigned_short_int_volatile )
- {
- test_atomic_integral_volatile<unsigned short int>();
- }
- TEST_F( cxx11_atomic_func, atomic_int )
- {
- test_atomic_integral<int>();
- }
- TEST_F( cxx11_atomic_func, atomic_int_volatile )
- {
- test_atomic_integral_volatile<int>();
- }
- TEST_F( cxx11_atomic_func, atomic_unsigned_int )
- {
- test_atomic_integral<unsigned int>();
- }
- TEST_F( cxx11_atomic_func, atomic_unsigned_int_volatile )
- {
- test_atomic_integral_volatile<unsigned int>();
- }
- TEST_F( cxx11_atomic_func, atomic_long )
- {
- test_atomic_integral<long>();
- }
- TEST_F( cxx11_atomic_func, atomic_long_volatile )
- {
- test_atomic_integral_volatile<long>();
- }
- TEST_F( cxx11_atomic_func, atomic_unsigned_long )
- {
- test_atomic_integral<unsigned long>();
- }
- TEST_F( cxx11_atomic_func, atomic_unsigned_long_volatile )
- {
- test_atomic_integral_volatile<unsigned long>();
- }
- TEST_F( cxx11_atomic_func, atomic_long_long )
- {
- test_atomic_integral<long long>();
- }
- TEST_F( cxx11_atomic_func, atomic_long_long_volatile )
- {
- test_atomic_integral_volatile<long long>();
- }
- TEST_F( cxx11_atomic_func, atomic_unsigned_long_long )
- {
- test_atomic_integral<unsigned long long>();
- }
- TEST_F( cxx11_atomic_func, atomic_unsigned_long_long_volatile )
- {
- test_atomic_integral_volatile<unsigned long long>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_void )
- {
- do_test_atomic_pointer_void<false>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_void_volatile )
- {
- do_test_atomic_pointer_void<true>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_char )
- {
- test_atomic_pointer_for<char, false>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_char_volatile )
- {
- test_atomic_pointer_for<char, true>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_short )
- {
- test_atomic_pointer_for<short, false>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_short_volatile )
- {
- test_atomic_pointer_for<short, true>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_int )
- {
- test_atomic_pointer_for<int, false>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_int_volatile )
- {
- test_atomic_pointer_for<int, true>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_long )
- {
- test_atomic_pointer_for<long, false>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_long_volatile )
- {
- test_atomic_pointer_for<long, true>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_long_long )
- {
- test_atomic_pointer_for<long long, false>();
- }
- TEST_F( cxx11_atomic_func, atomic_pointer_long_long_volatile )
- {
- test_atomic_pointer_for<long long, true>();
- }
- TEST_F( cxx11_atomic_func, test_atomic_fence )
- {
- atomics::atomic_thread_fence(atomics::memory_order_relaxed );
- atomics::atomic_thread_fence(atomics::memory_order_acquire );
- atomics::atomic_thread_fence(atomics::memory_order_release );
- atomics::atomic_thread_fence(atomics::memory_order_acq_rel );
- atomics::atomic_thread_fence(atomics::memory_order_seq_cst );
- atomics::atomic_signal_fence(atomics::memory_order_relaxed );
- atomics::atomic_signal_fence(atomics::memory_order_acquire );
- atomics::atomic_signal_fence(atomics::memory_order_release );
- atomics::atomic_signal_fence(atomics::memory_order_acq_rel );
- atomics::atomic_signal_fence(atomics::memory_order_seq_cst );
- }
- } // namespace
- #endif // #ifndef CDS_USE_BOOST_ATOMIC
|