cxx11_atomic_func.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. // Copyright (c) 2006-2018 Maxim Khizhinsky
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #include <cds_test/ext_gtest.h>
  6. #include <cds/algo/atomic.h>
  7. #ifndef CDS_USE_BOOST_ATOMIC
  8. // Skip this test for boost.atomic
  9. // Boost.atomic has no free atomic functions implementation.
  10. #include "cxx11_convert_memory_order.h"
  11. #define EXPECT_ATOMIC_IS_LOCK_FREE( x ) EXPECT_TRUE( atomics::atomic_is_lock_free( &x ));
  12. namespace misc {
  13. class cxx11_atomic_func: public ::testing::Test
  14. {
  15. protected:
  16. template <typename AtomicFlag>
  17. void do_test_atomic_flag_mo( AtomicFlag& f, atomics::memory_order order )
  18. {
  19. atomics::memory_order mo_clear = convert_to_store_order(order);
  20. f.clear( convert_to_store_order(order));
  21. for ( int i = 0; i < 5; ++i ) {
  22. EXPECT_FALSE( atomics::atomic_flag_test_and_set_explicit( &f, order ));
  23. EXPECT_TRUE( atomics::atomic_flag_test_and_set_explicit( &f, order ));
  24. atomics::atomic_flag_clear_explicit( &f, mo_clear );
  25. atomics::atomic_flag_clear_explicit( &f, mo_clear );
  26. }
  27. }
  28. template <typename AtomicFlag>
  29. void do_test_atomic_flag( AtomicFlag& f )
  30. {
  31. f.clear();
  32. for ( int i = 0; i < 5; ++i ) {
  33. EXPECT_FALSE( atomics::atomic_flag_test_and_set( &f ));
  34. EXPECT_TRUE( atomics::atomic_flag_test_and_set( &f ));
  35. atomics::atomic_flag_clear(&f);
  36. atomics::atomic_flag_clear(&f);
  37. }
  38. do_test_atomic_flag_mo( f, atomics::memory_order_relaxed );
  39. do_test_atomic_flag_mo( f, atomics::memory_order_acquire );
  40. do_test_atomic_flag_mo( f, atomics::memory_order_release );
  41. do_test_atomic_flag_mo( f, atomics::memory_order_acq_rel );
  42. do_test_atomic_flag_mo( f, atomics::memory_order_seq_cst );
  43. }
  44. template <class Atomic, typename Integral>
  45. void do_test_atomic_type(Atomic& a )
  46. {
  47. typedef Integral integral_type;
  48. EXPECT_ATOMIC_IS_LOCK_FREE( a );
  49. atomics::atomic_store( &a, (integral_type) 0 );
  50. EXPECT_EQ( atomics::atomic_load( &a ), integral_type( 0 ));
  51. for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
  52. integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
  53. EXPECT_EQ( atomics::atomic_exchange( &a, n ), (integral_type) 0 );
  54. EXPECT_EQ( atomics::atomic_load( &a ), n );
  55. EXPECT_EQ( atomics::atomic_exchange( &a, (integral_type) 0 ), n );
  56. EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) 0 );
  57. }
  58. integral_type prev = atomics::atomic_load( &a );
  59. for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
  60. integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
  61. integral_type expected = prev;
  62. EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &expected, n));
  63. EXPECT_EQ( expected, prev );
  64. EXPECT_NE( expected, n );
  65. EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &expected, n));
  66. EXPECT_EQ( expected, n );
  67. prev = n;
  68. EXPECT_EQ( atomics::atomic_load( &a ), n );
  69. }
  70. atomics::atomic_store( &a, (integral_type) 0 );
  71. prev = atomics::atomic_load( &a );
  72. for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
  73. integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
  74. integral_type expected = prev;
  75. EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &expected, n));
  76. EXPECT_EQ( expected, prev );
  77. EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &expected, n));
  78. EXPECT_EQ( expected, n );
  79. prev = n;
  80. EXPECT_EQ( atomics::atomic_load( &a ), n );
  81. }
  82. EXPECT_EQ( atomics::atomic_exchange( &a, (integral_type) 0 ), prev );
  83. }
  84. template <class Atomic, typename Integral>
  85. void do_test_atomic_integral( Atomic& a )
  86. {
  87. do_test_atomic_type< Atomic, Integral >( a );
  88. typedef Integral integral_type;
  89. // fetch_xxx testing
  90. atomics::atomic_store( &a, (integral_type) 0 );
  91. // fetch_add
  92. for ( size_t nByte = 0; nByte < sizeof(integral_type); ++nByte )
  93. {
  94. integral_type prev = atomics::atomic_load( &a );
  95. integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
  96. EXPECT_EQ( atomics::atomic_fetch_add( &a, n ), prev );
  97. }
  98. // fetch_sub
  99. for ( size_t nByte = sizeof(integral_type); nByte > 0; --nByte )
  100. {
  101. integral_type prev = atomics::atomic_load( &a );
  102. integral_type n = static_cast<integral_type>( integral_type(42) << ((nByte - 1) * 8));
  103. EXPECT_EQ( atomics::atomic_fetch_sub( &a, n ), prev );
  104. }
  105. EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) 0 );
  106. // fetch_or / fetc_xor / fetch_and
  107. for ( size_t nBit = 0; nBit < sizeof(integral_type) * 8; ++nBit )
  108. {
  109. integral_type prev = atomics::atomic_load( &a );
  110. integral_type mask = static_cast<integral_type>( integral_type(1) << nBit );
  111. EXPECT_EQ( atomics::atomic_fetch_or( &a, mask ), prev );
  112. prev = atomics::atomic_load( &a );
  113. EXPECT_EQ( ( prev & mask ), mask );
  114. EXPECT_EQ( atomics::atomic_fetch_and( &a, (integral_type) ~mask ), prev );
  115. prev = atomics::atomic_load( &a );
  116. EXPECT_EQ( integral_type(prev & mask), integral_type(0));
  117. EXPECT_EQ( atomics::atomic_fetch_xor( &a, mask ), prev );
  118. prev = atomics::atomic_load( &a );
  119. EXPECT_EQ( ( prev & mask), mask);
  120. }
  121. EXPECT_EQ( atomics::atomic_load( &a ), (integral_type) -1 );
  122. }
  123. template <class Atomic, typename Integral>
  124. void do_test_atomic_type( Atomic& a, atomics::memory_order order )
  125. {
  126. typedef Integral integral_type;
  127. const atomics::memory_order oLoad = convert_to_load_order( order );
  128. const atomics::memory_order oStore = convert_to_store_order( order );
  129. EXPECT_ATOMIC_IS_LOCK_FREE( a );
  130. atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
  131. EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) 0 );
  132. for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
  133. integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
  134. EXPECT_EQ( atomics::atomic_exchange_explicit( &a, n, order ), (integral_type) 0 );
  135. EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
  136. EXPECT_EQ( atomics::atomic_exchange_explicit( &a, (integral_type) 0, order ), n );
  137. EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) 0 );
  138. }
  139. integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
  140. for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
  141. integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
  142. integral_type expected = prev;
  143. EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
  144. EXPECT_EQ( expected, prev );
  145. EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
  146. EXPECT_EQ( expected, n );
  147. prev = n;
  148. EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
  149. }
  150. atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
  151. prev = atomics::atomic_load_explicit( &a, oLoad );
  152. for ( size_t nByte = 0; nByte < sizeof(Integral); ++nByte ) {
  153. integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
  154. integral_type expected = prev;
  155. EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
  156. EXPECT_EQ( expected, prev );
  157. EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, n, order, atomics::memory_order_relaxed));
  158. EXPECT_EQ( expected, n );
  159. prev = n;
  160. EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), n );
  161. }
  162. EXPECT_EQ( atomics::atomic_exchange_explicit( &a, (integral_type) 0, order ), prev );
  163. }
  164. template <class Atomic, typename Integral>
  165. void do_test_atomic_integral( Atomic& a, atomics::memory_order order )
  166. {
  167. do_test_atomic_type< Atomic, Integral >( a, order );
  168. typedef Integral integral_type;
  169. const atomics::memory_order oLoad = convert_to_load_order( order );
  170. const atomics::memory_order oStore = convert_to_store_order( order );
  171. // fetch_xxx testing
  172. atomics::atomic_store_explicit( &a, (integral_type) 0, oStore );
  173. // fetch_add
  174. for ( size_t nByte = 0; nByte < sizeof(integral_type); ++nByte )
  175. {
  176. integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
  177. integral_type n = static_cast<integral_type>( integral_type(42) << (nByte * 8));
  178. EXPECT_EQ( atomics::atomic_fetch_add_explicit( &a, n, order), prev);
  179. }
  180. // fetch_sub
  181. for ( size_t nByte = sizeof(integral_type); nByte > 0; --nByte )
  182. {
  183. integral_type prev = atomics::atomic_load_explicit( &a, oLoad );
  184. integral_type n = static_cast<integral_type>( integral_type(42) << ((nByte - 1) * 8));
  185. EXPECT_EQ( atomics::atomic_fetch_sub_explicit( &a, n, order ), prev);
  186. }
  187. EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), integral_type( 0 ));
  188. // fetch_or / fetc_xor / fetch_and
  189. for ( size_t nBit = 0; nBit < sizeof(integral_type) * 8; ++nBit )
  190. {
  191. integral_type prev = atomics::atomic_load_explicit( &a, oLoad ) ;;
  192. integral_type mask = static_cast<integral_type>( integral_type(1) << nBit );
  193. EXPECT_EQ( atomics::atomic_fetch_or_explicit( &a, mask, order ), prev );
  194. prev = atomics::atomic_load_explicit( &a, oLoad );
  195. EXPECT_EQ( ( prev & mask), mask);
  196. EXPECT_EQ( atomics::atomic_fetch_and_explicit( &a, (integral_type) ~mask, order ), prev );
  197. prev = atomics::atomic_load_explicit( &a, oLoad );
  198. EXPECT_EQ( ( prev & mask), integral_type( 0 ));
  199. EXPECT_EQ( atomics::atomic_fetch_xor_explicit( &a, mask, order ), prev );
  200. prev = atomics::atomic_load_explicit( &a, oLoad );
  201. EXPECT_EQ( ( prev & mask), mask);
  202. }
  203. EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), (integral_type) -1 );
  204. }
  205. template <typename Atomic, typename Integral>
  206. void test_atomic_integral_(Atomic& a)
  207. {
  208. do_test_atomic_integral<Atomic, Integral >(a);
  209. do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_relaxed );
  210. do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_acquire );
  211. do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_release );
  212. do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_acq_rel );
  213. do_test_atomic_integral<Atomic, Integral >( a, atomics::memory_order_seq_cst );
  214. }
  215. template <typename Integral>
  216. void test_atomic_integral()
  217. {
  218. typedef atomics::atomic<Integral> atomic_type;
  219. atomic_type a[8];
  220. for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
  221. test_atomic_integral_<atomic_type, Integral>( a[i] );
  222. }
  223. }
  224. template <typename Integral>
  225. void test_atomic_integral_volatile()
  226. {
  227. typedef atomics::atomic<Integral> volatile atomic_type;
  228. atomic_type a[8];
  229. for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
  230. test_atomic_integral_<atomic_type, Integral>( a[i] );
  231. }
  232. }
  233. template <class AtomicBool>
  234. void do_test_atomic_bool(AtomicBool& a)
  235. {
  236. EXPECT_ATOMIC_IS_LOCK_FREE( a );
  237. atomics::atomic_store( &a, false );
  238. EXPECT_FALSE( a );
  239. EXPECT_FALSE( atomics::atomic_load( &a ));
  240. EXPECT_FALSE( atomics::atomic_exchange( &a, true ));
  241. EXPECT_TRUE( atomics::atomic_load( &a ));
  242. EXPECT_TRUE( atomics::atomic_exchange( &a, false ));
  243. EXPECT_FALSE( atomics::atomic_load( &a ));
  244. bool expected = false;
  245. EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &expected, true));
  246. EXPECT_FALSE( expected );
  247. EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &expected, false));
  248. EXPECT_TRUE( expected );
  249. EXPECT_TRUE( atomics::atomic_load( &a ));
  250. atomics::atomic_store( &a, false );
  251. expected = false;
  252. EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &expected, true));
  253. EXPECT_FALSE( expected );
  254. EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &expected, false));
  255. EXPECT_TRUE( expected );
  256. EXPECT_TRUE( atomics::atomic_load( &a ));
  257. EXPECT_TRUE( atomics::atomic_exchange( &a, false ));
  258. }
  259. template <class AtomicBool>
  260. void do_test_atomic_bool( AtomicBool& a, atomics::memory_order order )
  261. {
  262. const atomics::memory_order oLoad = convert_to_load_order( order );
  263. const atomics::memory_order oStore = convert_to_store_order( order );
  264. const atomics::memory_order oExchange = convert_to_exchange_order( order );
  265. EXPECT_ATOMIC_IS_LOCK_FREE( a );
  266. atomics::atomic_store_explicit( &a, false, oStore );
  267. EXPECT_FALSE( a == false );
  268. EXPECT_FALSE( atomics::atomic_load_explicit( &a, oLoad ));
  269. EXPECT_FALSE( atomics::atomic_exchange_explicit( &a, true, oExchange ));
  270. EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
  271. EXPECT_TRUE( atomics::atomic_exchange_explicit( &a, false, oExchange ));
  272. EXPECT_FALSE( atomics::atomic_load_explicit( &a, oLoad ));
  273. bool expected = false;
  274. EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, true, order, atomics::memory_order_relaxed));
  275. EXPECT_FALSE( expected );
  276. EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &expected, false, order, atomics::memory_order_relaxed));
  277. EXPECT_TRUE( expected );
  278. EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
  279. atomics::atomic_store( &a, false );
  280. expected = false;
  281. EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, true, order, atomics::memory_order_relaxed));
  282. EXPECT_FALSE( expected );
  283. EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &expected, false, order, atomics::memory_order_relaxed));
  284. EXPECT_TRUE( expected );
  285. EXPECT_TRUE( atomics::atomic_load_explicit( &a, oLoad ));
  286. EXPECT_TRUE( atomics::atomic_exchange_explicit( &a, false, oExchange ));
  287. }
  288. template <typename Atomic, typename Integral>
  289. void test_atomic_pointer_for_( Atomic& a, Integral * arr, Integral aSize, atomics::memory_order order )
  290. {
  291. typedef Integral integral_type;
  292. atomics::memory_order oLoad = convert_to_load_order(order);
  293. atomics::memory_order oStore = convert_to_store_order(order);
  294. integral_type * p;
  295. atomics::atomic_store_explicit( &a, arr, oStore );
  296. EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), 1 );
  297. p = arr;
  298. EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, &p, arr + 5, order, atomics::memory_order_relaxed ));
  299. EXPECT_EQ( p, arr + 0 );
  300. EXPECT_EQ( *p, 1 );
  301. EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, &p, arr + 3, order, atomics::memory_order_relaxed ));
  302. EXPECT_EQ( p, arr + 5 );
  303. EXPECT_EQ( *p, 6 );
  304. EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, &p, arr + 3, order, atomics::memory_order_relaxed ));
  305. EXPECT_EQ( p, arr + 5 );
  306. EXPECT_EQ( *p, 6 );
  307. EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, &p, arr + 5, order, atomics::memory_order_relaxed ));
  308. EXPECT_EQ( p, arr + 3 );
  309. EXPECT_EQ( *p, 4 );
  310. EXPECT_EQ( atomics::atomic_exchange_explicit( &a, arr, order ), arr + 3 );
  311. EXPECT_EQ( atomics::atomic_load_explicit( &a, oLoad ), arr );
  312. EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), 1 );
  313. for ( integral_type i = 1; i < aSize; ++i ) {
  314. p = atomics::atomic_load_explicit( &a, oLoad );
  315. EXPECT_EQ( *p, i );
  316. EXPECT_EQ( atomics::atomic_fetch_add_explicit( &a, 1, order ), p );
  317. EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), i + 1 );
  318. }
  319. for ( integral_type i = aSize; i > 1; --i ) {
  320. p = atomics::atomic_load_explicit( &a, oLoad );
  321. EXPECT_EQ( *p, i );
  322. EXPECT_EQ( atomics::atomic_fetch_sub_explicit( &a, 1, order ), p );
  323. EXPECT_EQ( *atomics::atomic_load_explicit( &a, oLoad ), i - 1 );
  324. }
  325. }
  326. template <typename Integral, bool Volatile>
  327. void test_atomic_pointer_for()
  328. {
  329. typedef Integral integral_type;
  330. typedef typename add_volatile<atomics::atomic< integral_type *>, Volatile>::type atomic_pointer;
  331. integral_type arr[8];
  332. const integral_type aSize = sizeof(arr)/sizeof(arr[0]);
  333. for ( integral_type i = 0; i < aSize; ++i ) {
  334. arr[static_cast<size_t>(i)] = i + 1;
  335. }
  336. atomic_pointer a;
  337. integral_type * p;
  338. atomics::atomic_store( &a, arr );
  339. EXPECT_EQ( *atomics::atomic_load( &a ), 1 );
  340. p = arr;
  341. EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, &p, arr + 5 ));
  342. EXPECT_EQ( p, arr + 0 );
  343. EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, &p, arr + 3 ));
  344. EXPECT_EQ( p, arr + 5 );
  345. EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, &p, arr + 3 ));
  346. EXPECT_EQ( p, arr + 5 );
  347. EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, &p, arr + 5 ));
  348. EXPECT_EQ( p, arr + 3 );
  349. EXPECT_EQ( atomics::atomic_exchange( &a, arr ), arr + 3 );
  350. EXPECT_EQ( atomics::atomic_load( &a ), arr );
  351. EXPECT_EQ( *atomics::atomic_load( &a ), 1 );
  352. for ( integral_type i = 1; i < aSize; ++i ) {
  353. p = atomics::atomic_load( &a );
  354. EXPECT_EQ( *p, i );
  355. EXPECT_EQ( atomics::atomic_fetch_add( &a, 1 ), p );
  356. EXPECT_EQ( *atomics::atomic_load( &a ), i + 1 );
  357. }
  358. for ( integral_type i = aSize; i > 1; --i ) {
  359. p = atomics::atomic_load( &a );
  360. EXPECT_EQ( *p, i );
  361. EXPECT_EQ( atomics::atomic_fetch_sub( &a, 1 ), p );
  362. EXPECT_EQ( *atomics::atomic_load( &a ), i - 1 );
  363. }
  364. test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_relaxed );
  365. test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_acquire );
  366. test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_release );
  367. test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_acq_rel );
  368. test_atomic_pointer_for_( a, arr, aSize, atomics::memory_order_seq_cst );
  369. }
  370. template <typename Atomic>
  371. void do_test_atomic_pointer_void_( Atomic& a, char * arr, char aSize, atomics::memory_order order )
  372. {
  373. CDS_UNUSED( aSize );
  374. atomics::memory_order oLoad = convert_to_load_order(order);
  375. atomics::memory_order oStore = convert_to_store_order(order);
  376. char * p;
  377. atomics::atomic_store_explicit( &a, (void *) arr, oStore );
  378. EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), 1 );
  379. p = arr;
  380. EXPECT_TRUE( atomics::atomic_compare_exchange_weak_explicit( &a, (void **) &p, (void *)(arr + 5), order, atomics::memory_order_relaxed ));
  381. EXPECT_EQ( p, arr + 0 );
  382. EXPECT_EQ( *p, 1 );
  383. EXPECT_FALSE( atomics::atomic_compare_exchange_weak_explicit( &a, (void **) &p, (void *)(arr + 3), order, atomics::memory_order_relaxed ));
  384. EXPECT_EQ( p, arr + 5 );
  385. EXPECT_EQ( *p, 6 );
  386. EXPECT_TRUE( atomics::atomic_compare_exchange_strong_explicit( &a, (void **) &p, (void *)(arr + 3), order, atomics::memory_order_relaxed ));
  387. EXPECT_EQ( p, arr + 5 );
  388. EXPECT_EQ( *p, 6 );
  389. EXPECT_FALSE( atomics::atomic_compare_exchange_strong_explicit( &a, (void **) &p, (void *)(arr + 5), order, atomics::memory_order_relaxed ));
  390. EXPECT_EQ( p, arr + 3 );
  391. EXPECT_EQ( *p, 4 );
  392. EXPECT_EQ( reinterpret_cast<char *>(atomics::atomic_exchange_explicit( &a, (void *) arr, order )), arr + 3 );
  393. EXPECT_EQ( reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), arr );
  394. EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load_explicit( &a, oLoad )), 1 );
  395. }
  396. template <bool Volatile>
  397. void do_test_atomic_pointer_void()
  398. {
  399. typedef typename add_volatile<atomics::atomic< void *>, Volatile>::type atomic_pointer;
  400. char arr[8];
  401. const char aSize = sizeof(arr)/sizeof(arr[0]);
  402. for ( char i = 0; i < aSize; ++i ) {
  403. arr[static_cast<size_t>(i)] = i + 1;
  404. }
  405. atomic_pointer a;
  406. char * p;
  407. atomics::atomic_store( &a, (void *) arr );
  408. EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), 1 );
  409. p = arr;
  410. EXPECT_TRUE( atomics::atomic_compare_exchange_weak( &a, (void **) &p, (void *)(arr + 5)));
  411. EXPECT_EQ( p, arr + 0 );
  412. EXPECT_FALSE( atomics::atomic_compare_exchange_weak( &a, (void **) &p, (void *)(arr + 3)));
  413. EXPECT_EQ( p, arr + 5 );
  414. EXPECT_TRUE( atomics::atomic_compare_exchange_strong( &a, (void **) &p, (void *)(arr + 3)));
  415. EXPECT_EQ( p, arr + 5 );
  416. EXPECT_FALSE( atomics::atomic_compare_exchange_strong( &a, (void **) &p, (void *)(arr + 5)));
  417. EXPECT_EQ( p, arr + 3 );
  418. EXPECT_EQ( reinterpret_cast<char *>( atomics::atomic_exchange( &a, (void *) arr )), arr + 3 );
  419. EXPECT_EQ( reinterpret_cast<char *>( atomics::atomic_load( &a )), arr );
  420. EXPECT_EQ( *reinterpret_cast<char *>(atomics::atomic_load( &a )), 1 );
  421. do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_relaxed );
  422. do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_acquire );
  423. do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_release );
  424. do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_acq_rel );
  425. do_test_atomic_pointer_void_( a, arr, aSize, atomics::memory_order_seq_cst );
  426. }
  427. public:
  428. void test_atomic_flag()
  429. {
  430. atomics::atomic_flag flags[8];
  431. for ( size_t i = 0; i < sizeof(flags)/sizeof(flags[0]); ++i )
  432. do_test_atomic_flag( flags[i] );
  433. }
  434. void test_atomic_flag_volatile()
  435. {
  436. atomics::atomic_flag volatile flags[8];
  437. for ( size_t i = 0; i < sizeof(flags)/sizeof(flags[0]); ++i )
  438. do_test_atomic_flag( flags[i] );
  439. }
  440. template <typename AtomicBool>
  441. void test_atomic_bool_()
  442. {
  443. AtomicBool a[8];
  444. for ( size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i ) {
  445. do_test_atomic_bool( a[i] );
  446. do_test_atomic_bool( a[i], atomics::memory_order_relaxed );
  447. do_test_atomic_bool( a[i], atomics::memory_order_acquire );
  448. do_test_atomic_bool( a[i], atomics::memory_order_release );
  449. do_test_atomic_bool( a[i], atomics::memory_order_acq_rel );
  450. do_test_atomic_bool( a[i], atomics::memory_order_seq_cst );
  451. }
  452. }
  453. void test_atomic_bool()
  454. {
  455. test_atomic_bool_<atomics::atomic<bool> >();
  456. }
  457. void test_atomic_bool_volatile()
  458. {
  459. test_atomic_bool_<atomics::atomic<bool> volatile >();
  460. }
  461. };
  462. TEST_F( cxx11_atomic_func, atomic_char )
  463. {
  464. test_atomic_integral<char>();
  465. }
  466. TEST_F( cxx11_atomic_func, atomic_char_volatile )
  467. {
  468. test_atomic_integral_volatile<char>();
  469. }
  470. TEST_F( cxx11_atomic_func, atomic_unsigned_char )
  471. {
  472. test_atomic_integral<unsigned char>();
  473. }
  474. TEST_F( cxx11_atomic_func, atomic_unsigned_char_volatile )
  475. {
  476. test_atomic_integral_volatile<unsigned char>();
  477. }
  478. TEST_F( cxx11_atomic_func, atomic_signed_char )
  479. {
  480. test_atomic_integral<signed char>();
  481. }
  482. TEST_F( cxx11_atomic_func, atomic_signed_char_volatile )
  483. {
  484. test_atomic_integral_volatile<signed char>();
  485. }
  486. TEST_F( cxx11_atomic_func, atomic_short_int )
  487. {
  488. test_atomic_integral<short int>();
  489. }
  490. TEST_F( cxx11_atomic_func, atomic_short_int_volatile )
  491. {
  492. test_atomic_integral_volatile<short int>();
  493. }
  494. TEST_F( cxx11_atomic_func, atomic_unsigned_short_int )
  495. {
  496. test_atomic_integral<unsigned short int>();
  497. }
  498. TEST_F( cxx11_atomic_func, atomic_unsigned_short_int_volatile )
  499. {
  500. test_atomic_integral_volatile<unsigned short int>();
  501. }
  502. TEST_F( cxx11_atomic_func, atomic_int )
  503. {
  504. test_atomic_integral<int>();
  505. }
  506. TEST_F( cxx11_atomic_func, atomic_int_volatile )
  507. {
  508. test_atomic_integral_volatile<int>();
  509. }
  510. TEST_F( cxx11_atomic_func, atomic_unsigned_int )
  511. {
  512. test_atomic_integral<unsigned int>();
  513. }
  514. TEST_F( cxx11_atomic_func, atomic_unsigned_int_volatile )
  515. {
  516. test_atomic_integral_volatile<unsigned int>();
  517. }
  518. TEST_F( cxx11_atomic_func, atomic_long )
  519. {
  520. test_atomic_integral<long>();
  521. }
  522. TEST_F( cxx11_atomic_func, atomic_long_volatile )
  523. {
  524. test_atomic_integral_volatile<long>();
  525. }
  526. TEST_F( cxx11_atomic_func, atomic_unsigned_long )
  527. {
  528. test_atomic_integral<unsigned long>();
  529. }
  530. TEST_F( cxx11_atomic_func, atomic_unsigned_long_volatile )
  531. {
  532. test_atomic_integral_volatile<unsigned long>();
  533. }
  534. TEST_F( cxx11_atomic_func, atomic_long_long )
  535. {
  536. test_atomic_integral<long long>();
  537. }
  538. TEST_F( cxx11_atomic_func, atomic_long_long_volatile )
  539. {
  540. test_atomic_integral_volatile<long long>();
  541. }
  542. TEST_F( cxx11_atomic_func, atomic_unsigned_long_long )
  543. {
  544. test_atomic_integral<unsigned long long>();
  545. }
  546. TEST_F( cxx11_atomic_func, atomic_unsigned_long_long_volatile )
  547. {
  548. test_atomic_integral_volatile<unsigned long long>();
  549. }
  550. TEST_F( cxx11_atomic_func, atomic_pointer_void )
  551. {
  552. do_test_atomic_pointer_void<false>();
  553. }
  554. TEST_F( cxx11_atomic_func, atomic_pointer_void_volatile )
  555. {
  556. do_test_atomic_pointer_void<true>();
  557. }
  558. TEST_F( cxx11_atomic_func, atomic_pointer_char )
  559. {
  560. test_atomic_pointer_for<char, false>();
  561. }
  562. TEST_F( cxx11_atomic_func, atomic_pointer_char_volatile )
  563. {
  564. test_atomic_pointer_for<char, true>();
  565. }
  566. TEST_F( cxx11_atomic_func, atomic_pointer_short )
  567. {
  568. test_atomic_pointer_for<short, false>();
  569. }
  570. TEST_F( cxx11_atomic_func, atomic_pointer_short_volatile )
  571. {
  572. test_atomic_pointer_for<short, true>();
  573. }
  574. TEST_F( cxx11_atomic_func, atomic_pointer_int )
  575. {
  576. test_atomic_pointer_for<int, false>();
  577. }
  578. TEST_F( cxx11_atomic_func, atomic_pointer_int_volatile )
  579. {
  580. test_atomic_pointer_for<int, true>();
  581. }
  582. TEST_F( cxx11_atomic_func, atomic_pointer_long )
  583. {
  584. test_atomic_pointer_for<long, false>();
  585. }
  586. TEST_F( cxx11_atomic_func, atomic_pointer_long_volatile )
  587. {
  588. test_atomic_pointer_for<long, true>();
  589. }
  590. TEST_F( cxx11_atomic_func, atomic_pointer_long_long )
  591. {
  592. test_atomic_pointer_for<long long, false>();
  593. }
  594. TEST_F( cxx11_atomic_func, atomic_pointer_long_long_volatile )
  595. {
  596. test_atomic_pointer_for<long long, true>();
  597. }
  598. TEST_F( cxx11_atomic_func, test_atomic_fence )
  599. {
  600. atomics::atomic_thread_fence(atomics::memory_order_relaxed );
  601. atomics::atomic_thread_fence(atomics::memory_order_acquire );
  602. atomics::atomic_thread_fence(atomics::memory_order_release );
  603. atomics::atomic_thread_fence(atomics::memory_order_acq_rel );
  604. atomics::atomic_thread_fence(atomics::memory_order_seq_cst );
  605. atomics::atomic_signal_fence(atomics::memory_order_relaxed );
  606. atomics::atomic_signal_fence(atomics::memory_order_acquire );
  607. atomics::atomic_signal_fence(atomics::memory_order_release );
  608. atomics::atomic_signal_fence(atomics::memory_order_acq_rel );
  609. atomics::atomic_signal_fence(atomics::memory_order_seq_cst );
  610. }
  611. } // namespace
  612. #endif // #ifndef CDS_USE_BOOST_ATOMIC