Atomics.cpp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. // Converted from libcxx's tests
  9. // https://github.com/llvm-mirror/libcxx/tree/7175a079211ec78c8232d9d55fa4c1f9eeae803d/test/AZStd/atomics/
  10. // convert assert -> EXPECT_TRUE
  11. // convert EXPECT_TRUE\((.+)\s*==\s*(.+)\); -> EXPECT_EQ($2, $1);
  12. // * Exception: gtest cannot deal with atomic<T>::operator==, nor can it print the value, so these stay as-is
  13. // convert std:: -> AZStd::
  14. // convert T -> TypeParam
  15. // remove constexpr
  16. #include "UserTypes.h"
  17. #include <AzCore/std/parallel/atomic.h>
  18. namespace UnitTest
  19. {
  20. class Atomics
  21. : public LeakDetectionFixture
  22. {
  23. };
  24. template <class A, class T>
  25. bool cmpxchg_weak_loop(A& atomic, T& expected, T desired)
  26. {
  27. for (int i = 0; i < 10; i++)
  28. {
  29. if (atomic.compare_exchange_weak(expected, desired) == true)
  30. {
  31. return true;
  32. }
  33. }
  34. return false;
  35. }
  36. template <class A, class T>
  37. bool cmpxchg_weak_loop(A& atomic, T& expected, T desired, AZStd::memory_order success, AZStd::memory_order failure)
  38. {
  39. for (int i = 0; i < 10; i++)
  40. {
  41. if (atomic.compare_exchange_weak(expected, desired, success, failure) == true)
  42. {
  43. return true;
  44. }
  45. }
  46. return false;
  47. }
  48. template <class A, class T>
  49. bool c_cmpxchg_weak_loop(A* atomic, T* expected, T desired)
  50. {
  51. for (int i = 0; i < 10; i++)
  52. {
  53. if (AZStd::atomic_compare_exchange_weak(atomic, expected, desired) == true)
  54. {
  55. return true;
  56. }
  57. }
  58. return false;
  59. }
  60. template <class A, class T>
  61. bool c_cmpxchg_weak_loop(A* atomic, T* expected, T desired, AZStd::memory_order success, AZStd::memory_order failure)
  62. {
  63. for (int i = 0; i < 10; i++)
  64. {
  65. if (AZStd::atomic_compare_exchange_weak_explicit(atomic, expected, desired, success, failure) == true)
  66. {
  67. return true;
  68. }
  69. }
  70. return false;
  71. }
  72. struct IntWrapper
  73. {
  74. int i;
  75. explicit IntWrapper(int d = 0) { i = d; }
  76. friend bool operator==(const IntWrapper& x, const IntWrapper& y)
  77. {
  78. return x.i == y.i;
  79. }
  80. };
  81. using AllAtomicTypes = ::testing::Types<
  82. char,
  83. unsigned char,
  84. short,
  85. unsigned short,
  86. int,
  87. unsigned int,
  88. long,
  89. unsigned long,
  90. long long,
  91. unsigned long long,
  92. wchar_t,
  93. int*,
  94. const int*
  95. >;
  96. using IntegralAtomicTypes = ::testing::Types<
  97. char,
  98. unsigned char,
  99. short,
  100. unsigned short,
  101. int,
  102. unsigned int,
  103. long,
  104. unsigned long,
  105. long long,
  106. unsigned long long,
  107. wchar_t
  108. >;
  109. using PointerAtomicTypes = ::testing::Types<
  110. int*,
  111. const int*
  112. >;
  113. template <class T>
  114. struct AtomicOps : public Atomics {};
  115. template <class T>
  116. struct AtomicOpsIntegral : public Atomics {};
  117. template <class T>
  118. struct AtomicOpsPointer : public Atomics {};
  119. TYPED_TEST_SUITE(AtomicOps, AllAtomicTypes);
  120. TYPED_TEST_SUITE(AtomicOpsIntegral, IntegralAtomicTypes);
  121. TYPED_TEST_SUITE(AtomicOpsPointer, PointerAtomicTypes);
  122. TYPED_TEST(AtomicOps, CompareExchangeStrong)
  123. {
  124. {
  125. typedef AZStd::atomic<TypeParam> A;
  126. A a;
  127. TypeParam t(TypeParam(1));
  128. AZStd::atomic_init(&a, t);
  129. EXPECT_TRUE(AZStd::atomic_compare_exchange_strong(&a, &t, TypeParam(2)));
  130. EXPECT_TRUE(TypeParam(2) == a);
  131. EXPECT_TRUE(TypeParam(1) == t);
  132. EXPECT_FALSE(AZStd::atomic_compare_exchange_strong(&a, &t, TypeParam(3)));
  133. EXPECT_TRUE(TypeParam(2) == a);
  134. EXPECT_TRUE(TypeParam(2) == t);
  135. }
  136. {
  137. typedef AZStd::atomic<TypeParam> A;
  138. volatile A a;
  139. TypeParam t(TypeParam(1));
  140. AZStd::atomic_init(&a, t);
  141. EXPECT_TRUE(AZStd::atomic_compare_exchange_strong(&a, &t, TypeParam(2)));
  142. EXPECT_TRUE(TypeParam(2) == a);
  143. EXPECT_TRUE(TypeParam(1) == t);
  144. EXPECT_FALSE(AZStd::atomic_compare_exchange_strong(&a, &t, TypeParam(3)));
  145. EXPECT_TRUE(TypeParam(2) == a);
  146. EXPECT_TRUE(TypeParam(2) == t);
  147. }
  148. }
  149. TYPED_TEST(AtomicOps, CompareExchangeStrongExplicit)
  150. {
  151. {
  152. typedef AZStd::atomic<TypeParam> A;
  153. A a;
  154. TypeParam t(TypeParam(1));
  155. AZStd::atomic_init(&a, t);
  156. EXPECT_TRUE(AZStd::atomic_compare_exchange_strong_explicit(&a, &t, TypeParam(2), AZStd::memory_order_seq_cst, AZStd::memory_order_seq_cst));
  157. EXPECT_TRUE(TypeParam(2) == a);
  158. EXPECT_TRUE(TypeParam(1) == t);
  159. EXPECT_FALSE(AZStd::atomic_compare_exchange_strong_explicit(&a, &t, TypeParam(3), AZStd::memory_order_seq_cst, AZStd::memory_order_seq_cst));
  160. EXPECT_TRUE(TypeParam(2) == a);
  161. EXPECT_TRUE(TypeParam(2) == t);
  162. }
  163. {
  164. typedef AZStd::atomic<TypeParam> A;
  165. volatile A a;
  166. TypeParam t(TypeParam(1));
  167. AZStd::atomic_init(&a, t);
  168. EXPECT_TRUE(AZStd::atomic_compare_exchange_strong_explicit(&a, &t, TypeParam(2), AZStd::memory_order_seq_cst, AZStd::memory_order_seq_cst));
  169. EXPECT_TRUE(TypeParam(2) == a);
  170. EXPECT_TRUE(TypeParam(1) == t);
  171. EXPECT_FALSE(AZStd::atomic_compare_exchange_strong_explicit(&a, &t, TypeParam(3), AZStd::memory_order_seq_cst, AZStd::memory_order_seq_cst));
  172. EXPECT_TRUE(TypeParam(2) == a);
  173. EXPECT_TRUE(TypeParam(2) == t);
  174. }
  175. }
  176. TYPED_TEST(AtomicOps, CompareExchangeWeak)
  177. {
  178. {
  179. typedef AZStd::atomic<TypeParam> A;
  180. A a;
  181. TypeParam t(TypeParam(1));
  182. AZStd::atomic_init(&a, t);
  183. EXPECT_TRUE(c_cmpxchg_weak_loop(&a, &t, TypeParam(2)));
  184. EXPECT_TRUE(TypeParam(2) == a);
  185. EXPECT_TRUE(TypeParam(1) == t);
  186. EXPECT_FALSE(AZStd::atomic_compare_exchange_weak(&a, &t, TypeParam(3)));
  187. EXPECT_TRUE(TypeParam(2) == a);
  188. EXPECT_TRUE(TypeParam(2) == t);
  189. }
  190. {
  191. typedef AZStd::atomic<TypeParam> A;
  192. volatile A a;
  193. TypeParam t(TypeParam(1));
  194. AZStd::atomic_init(&a, t);
  195. EXPECT_TRUE(c_cmpxchg_weak_loop(&a, &t, TypeParam(2)));
  196. EXPECT_TRUE(TypeParam(2) == a);
  197. EXPECT_TRUE(TypeParam(1) == t);
  198. EXPECT_FALSE(AZStd::atomic_compare_exchange_weak(&a, &t, TypeParam(3)));
  199. EXPECT_TRUE(TypeParam(2) == a);
  200. EXPECT_TRUE(TypeParam(2) == t);
  201. }
  202. }
  203. TYPED_TEST(AtomicOps, CompareExchangeWeakExplicit)
  204. {
  205. {
  206. typedef AZStd::atomic<TypeParam> A;
  207. A a;
  208. TypeParam t(TypeParam(1));
  209. AZStd::atomic_init(&a, t);
  210. EXPECT_TRUE(c_cmpxchg_weak_loop(&a, &t, TypeParam(2), AZStd::memory_order_seq_cst, AZStd::memory_order_seq_cst));
  211. EXPECT_TRUE(a == TypeParam(2));
  212. EXPECT_TRUE(t == TypeParam(1));
  213. EXPECT_FALSE(AZStd::atomic_compare_exchange_weak_explicit(&a, &t, TypeParam(3), AZStd::memory_order_seq_cst, AZStd::memory_order_seq_cst));
  214. EXPECT_TRUE(a == TypeParam(2));
  215. EXPECT_TRUE(t == TypeParam(2));
  216. }
  217. {
  218. typedef AZStd::atomic<TypeParam> A;
  219. volatile A a;
  220. TypeParam t(TypeParam(1));
  221. AZStd::atomic_init(&a, t);
  222. EXPECT_TRUE(c_cmpxchg_weak_loop(&a, &t, TypeParam(2), AZStd::memory_order_seq_cst, AZStd::memory_order_seq_cst));
  223. EXPECT_TRUE(a == TypeParam(2));
  224. EXPECT_TRUE(t == TypeParam(1));
  225. EXPECT_FALSE(AZStd::atomic_compare_exchange_weak_explicit(&a, &t, TypeParam(3), AZStd::memory_order_seq_cst, AZStd::memory_order_seq_cst));
  226. EXPECT_TRUE(a == TypeParam(2));
  227. EXPECT_TRUE(t == TypeParam(2));
  228. }
  229. }
  230. TYPED_TEST(AtomicOps, Exchange)
  231. {
  232. typedef AZStd::atomic<TypeParam> A;
  233. A t;
  234. AZStd::atomic_init(&t, TypeParam(1));
  235. EXPECT_TRUE(AZStd::atomic_exchange(&t, TypeParam(2)) == TypeParam(1));
  236. EXPECT_TRUE(t == TypeParam(2));
  237. volatile A vt;
  238. AZStd::atomic_init(&vt, TypeParam(3));
  239. EXPECT_TRUE(AZStd::atomic_exchange(&vt, TypeParam(4)) == TypeParam(3));
  240. EXPECT_TRUE(vt == TypeParam(4));
  241. }
  242. TYPED_TEST(AtomicOps, ExchangeExplicit)
  243. {
  244. typedef AZStd::atomic<TypeParam> A;
  245. A t;
  246. AZStd::atomic_init(&t, TypeParam(1));
  247. EXPECT_TRUE(AZStd::atomic_exchange_explicit(&t, TypeParam(2), AZStd::memory_order_seq_cst) == TypeParam(1));
  248. EXPECT_TRUE(t == TypeParam(2));
  249. volatile A vt;
  250. AZStd::atomic_init(&vt, TypeParam(3));
  251. EXPECT_TRUE(AZStd::atomic_exchange_explicit(&vt, TypeParam(4), AZStd::memory_order_seq_cst) == TypeParam(3));
  252. EXPECT_TRUE(vt == TypeParam(4));
  253. }
  254. TYPED_TEST(AtomicOpsIntegral, FetchAdd)
  255. {
  256. {
  257. typedef AZStd::atomic<TypeParam> A;
  258. A t;
  259. AZStd::atomic_init(&t, TypeParam(1));
  260. EXPECT_TRUE(AZStd::atomic_fetch_add(&t, TypeParam(2)) == TypeParam(1));
  261. EXPECT_TRUE(t == TypeParam(3));
  262. }
  263. {
  264. typedef AZStd::atomic<TypeParam> A;
  265. volatile A t;
  266. AZStd::atomic_init(&t, TypeParam(1));
  267. EXPECT_TRUE(AZStd::atomic_fetch_add(&t, TypeParam(2)) == TypeParam(1));
  268. EXPECT_TRUE(t == TypeParam(3));
  269. }
  270. }
  271. TYPED_TEST(AtomicOpsPointer, FetchAdd)
  272. {
  273. {
  274. typedef AZStd::atomic<TypeParam> A;
  275. typedef typename AZStd::remove_pointer<TypeParam>::type X;
  276. A t;
  277. AZStd::atomic_init(&t, TypeParam(1 * sizeof(X)));
  278. EXPECT_TRUE(AZStd::atomic_fetch_add(&t, 2) == TypeParam(1 * sizeof(X)));
  279. EXPECT_TRUE(t == TypeParam(3 * sizeof(X)));
  280. }
  281. {
  282. typedef AZStd::atomic<TypeParam> A;
  283. typedef typename AZStd::remove_pointer<TypeParam>::type X;
  284. volatile A t;
  285. AZStd::atomic_init(&t, TypeParam(1 * sizeof(X)));
  286. EXPECT_TRUE(AZStd::atomic_fetch_add(&t, 2) == TypeParam(1 * sizeof(X)));
  287. EXPECT_TRUE(t == TypeParam(3 * sizeof(X)));
  288. }
  289. }
  290. TYPED_TEST(AtomicOpsIntegral, FetchAddExplicit)
  291. {
  292. {
  293. typedef AZStd::atomic<TypeParam> A;
  294. A t;
  295. AZStd::atomic_init(&t, TypeParam(1));
  296. EXPECT_TRUE(AZStd::atomic_fetch_add_explicit(&t, TypeParam(2), AZStd::memory_order_seq_cst) == TypeParam(1));
  297. EXPECT_TRUE(t == TypeParam(3));
  298. }
  299. {
  300. typedef AZStd::atomic<TypeParam> A;
  301. volatile A t;
  302. AZStd::atomic_init(&t, TypeParam(1));
  303. EXPECT_TRUE(AZStd::atomic_fetch_add_explicit(&t, TypeParam(2), AZStd::memory_order_seq_cst) == TypeParam(1));
  304. EXPECT_TRUE(t == TypeParam(3));
  305. }
  306. }
  307. TYPED_TEST(AtomicOpsPointer, FetchAddExplicit)
  308. {
  309. {
  310. typedef AZStd::atomic<TypeParam> A;
  311. typedef typename AZStd::remove_pointer<TypeParam>::type X;
  312. A t;
  313. AZStd::atomic_init(&t, TypeParam(1 * sizeof(X)));
  314. EXPECT_TRUE(AZStd::atomic_fetch_add_explicit(&t, 2, AZStd::memory_order_seq_cst) == TypeParam(1 * sizeof(X)));
  315. EXPECT_TRUE(t == TypeParam(3 * sizeof(X)));
  316. }
  317. {
  318. typedef AZStd::atomic<TypeParam> A;
  319. typedef typename AZStd::remove_pointer<TypeParam>::type X;
  320. volatile A t;
  321. AZStd::atomic_init(&t, TypeParam(1 * sizeof(X)));
  322. EXPECT_TRUE(AZStd::atomic_fetch_add_explicit(&t, 2, AZStd::memory_order_seq_cst) == TypeParam(1 * sizeof(X)));
  323. EXPECT_TRUE(t == TypeParam(3 * sizeof(X)));
  324. }
  325. }
  326. TYPED_TEST(AtomicOpsIntegral, FetchAnd)
  327. {
  328. {
  329. typedef AZStd::atomic<TypeParam> A;
  330. A t;
  331. AZStd::atomic_init(&t, TypeParam(1));
  332. EXPECT_TRUE(AZStd::atomic_fetch_and(&t, TypeParam(2)) == TypeParam(1));
  333. EXPECT_TRUE(t == TypeParam(0));
  334. }
  335. {
  336. typedef AZStd::atomic<TypeParam> A;
  337. volatile A t;
  338. AZStd::atomic_init(&t, TypeParam(3));
  339. EXPECT_TRUE(AZStd::atomic_fetch_and(&t, TypeParam(2)) == TypeParam(3));
  340. EXPECT_TRUE(t == TypeParam(2));
  341. }
  342. }
  343. TYPED_TEST(AtomicOpsIntegral, FetchAndExplicit)
  344. {
  345. {
  346. typedef AZStd::atomic<TypeParam> A;
  347. A t;
  348. AZStd::atomic_init(&t, TypeParam(1));
  349. EXPECT_TRUE(AZStd::atomic_fetch_and_explicit(&t, TypeParam(2),
  350. AZStd::memory_order_seq_cst) == TypeParam(1));
  351. EXPECT_TRUE(t == TypeParam(0));
  352. }
  353. {
  354. typedef AZStd::atomic<TypeParam> A;
  355. volatile A t;
  356. AZStd::atomic_init(&t, TypeParam(3));
  357. EXPECT_TRUE(AZStd::atomic_fetch_and_explicit(&t, TypeParam(2),
  358. AZStd::memory_order_seq_cst) == TypeParam(3));
  359. EXPECT_TRUE(t == TypeParam(2));
  360. }
  361. }
  362. TYPED_TEST(AtomicOpsIntegral, FetchOr)
  363. {
  364. {
  365. typedef AZStd::atomic<TypeParam> A;
  366. A t;
  367. AZStd::atomic_init(&t, TypeParam(1));
  368. EXPECT_TRUE(AZStd::atomic_fetch_or(&t, TypeParam(2)) == TypeParam(1));
  369. EXPECT_TRUE(t == TypeParam(3));
  370. }
  371. {
  372. typedef AZStd::atomic<TypeParam> A;
  373. volatile A t;
  374. AZStd::atomic_init(&t, TypeParam(3));
  375. EXPECT_TRUE(AZStd::atomic_fetch_or(&t, TypeParam(2)) == TypeParam(3));
  376. EXPECT_TRUE(t == TypeParam(3));
  377. }
  378. }
  379. TYPED_TEST(AtomicOpsIntegral, FetchOrExplicit)
  380. {
  381. {
  382. typedef AZStd::atomic<TypeParam> A;
  383. A t;
  384. AZStd::atomic_init(&t, TypeParam(1));
  385. EXPECT_TRUE(AZStd::atomic_fetch_or_explicit(&t, TypeParam(2),
  386. AZStd::memory_order_seq_cst) == TypeParam(1));
  387. EXPECT_TRUE(t == TypeParam(3));
  388. }
  389. {
  390. typedef AZStd::atomic<TypeParam> A;
  391. volatile A t;
  392. AZStd::atomic_init(&t, TypeParam(3));
  393. EXPECT_TRUE(AZStd::atomic_fetch_or_explicit(&t, TypeParam(2),
  394. AZStd::memory_order_seq_cst) == TypeParam(3));
  395. EXPECT_TRUE(t == TypeParam(3));
  396. }
  397. }
  398. TYPED_TEST(AtomicOpsIntegral, FetchSub)
  399. {
  400. {
  401. typedef AZStd::atomic<TypeParam> A;
  402. A t;
  403. AZStd::atomic_init(&t, TypeParam(3));
  404. EXPECT_TRUE(AZStd::atomic_fetch_sub(&t, TypeParam(2)) == TypeParam(3));
  405. EXPECT_TRUE(t == TypeParam(1));
  406. }
  407. {
  408. typedef AZStd::atomic<TypeParam> A;
  409. volatile A t;
  410. AZStd::atomic_init(&t, TypeParam(3));
  411. EXPECT_TRUE(AZStd::atomic_fetch_sub(&t, TypeParam(2)) == TypeParam(3));
  412. EXPECT_TRUE(t == TypeParam(1));
  413. }
  414. }
  415. TYPED_TEST(AtomicOpsIntegral, FetchSubExplicit)
  416. {
  417. {
  418. typedef AZStd::atomic<TypeParam> A;
  419. A t;
  420. AZStd::atomic_init(&t, TypeParam(3));
  421. EXPECT_TRUE(AZStd::atomic_fetch_sub_explicit(&t, TypeParam(2),
  422. AZStd::memory_order_seq_cst) == TypeParam(3));
  423. EXPECT_TRUE(t == TypeParam(1));
  424. }
  425. {
  426. typedef AZStd::atomic<TypeParam> A;
  427. volatile A t;
  428. AZStd::atomic_init(&t, TypeParam(3));
  429. EXPECT_TRUE(AZStd::atomic_fetch_sub_explicit(&t, TypeParam(2),
  430. AZStd::memory_order_seq_cst) == TypeParam(3));
  431. EXPECT_TRUE(t == TypeParam(1));
  432. }
  433. }
  434. TYPED_TEST(AtomicOpsIntegral, FetchXor)
  435. {
  436. {
  437. typedef AZStd::atomic<TypeParam> A;
  438. A t;
  439. AZStd::atomic_init(&t, TypeParam(1));
  440. EXPECT_TRUE(AZStd::atomic_fetch_xor(&t, TypeParam(2)) == TypeParam(1));
  441. EXPECT_TRUE(t == TypeParam(3));
  442. }
  443. {
  444. typedef AZStd::atomic<TypeParam> A;
  445. volatile A t;
  446. AZStd::atomic_init(&t, TypeParam(3));
  447. EXPECT_TRUE(AZStd::atomic_fetch_xor(&t, TypeParam(2)) == TypeParam(3));
  448. EXPECT_TRUE(t == TypeParam(1));
  449. }
  450. }
  451. TYPED_TEST(AtomicOpsIntegral, FetchXorExplicit)
  452. {
  453. {
  454. typedef AZStd::atomic<TypeParam> A;
  455. A t;
  456. AZStd::atomic_init(&t, TypeParam(1));
  457. EXPECT_TRUE(AZStd::atomic_fetch_xor_explicit(&t, TypeParam(2),
  458. AZStd::memory_order_seq_cst) == TypeParam(1));
  459. EXPECT_TRUE(t == TypeParam(3));
  460. }
  461. {
  462. typedef AZStd::atomic<TypeParam> A;
  463. volatile A t;
  464. AZStd::atomic_init(&t, TypeParam(3));
  465. EXPECT_TRUE(AZStd::atomic_fetch_xor_explicit(&t, TypeParam(2),
  466. AZStd::memory_order_seq_cst) == TypeParam(3));
  467. EXPECT_TRUE(t == TypeParam(1));
  468. }
  469. }
  470. TYPED_TEST(AtomicOps, Init)
  471. {
  472. typedef AZStd::atomic<TypeParam> A;
  473. A t;
  474. AZStd::atomic_init(&t, TypeParam(1));
  475. EXPECT_TRUE(t == TypeParam(1));
  476. volatile A vt;
  477. AZStd::atomic_init(&vt, TypeParam(2));
  478. EXPECT_TRUE(vt == TypeParam(2));
  479. }
  480. TYPED_TEST(AtomicOps, IsLockFree)
  481. {
  482. typedef AZStd::atomic<TypeParam> A;
  483. A t;
  484. bool b1 = AZStd::atomic_is_lock_free(static_cast<const A*>(&t));
  485. volatile A vt;
  486. bool b2 = AZStd::atomic_is_lock_free(static_cast<const volatile A*>(&vt));
  487. EXPECT_TRUE(b1 == b2);
  488. }
  489. TYPED_TEST(AtomicOps, Load)
  490. {
  491. typedef AZStd::atomic<TypeParam> A;
  492. A t;
  493. AZStd::atomic_init(&t, TypeParam(1));
  494. EXPECT_TRUE(AZStd::atomic_load(&t) == TypeParam(1));
  495. volatile A vt;
  496. AZStd::atomic_init(&vt, TypeParam(2));
  497. EXPECT_TRUE(AZStd::atomic_load(&vt) == TypeParam(2));
  498. }
  499. TYPED_TEST(AtomicOps, LoadExplicit)
  500. {
  501. typedef AZStd::atomic<TypeParam> A;
  502. A t;
  503. AZStd::atomic_init(&t, TypeParam(1));
  504. EXPECT_TRUE(AZStd::atomic_load_explicit(&t, AZStd::memory_order_seq_cst) == TypeParam(1));
  505. volatile A vt;
  506. AZStd::atomic_init(&vt, TypeParam(2));
  507. EXPECT_TRUE(AZStd::atomic_load_explicit(&vt, AZStd::memory_order_seq_cst) == TypeParam(2));
  508. }
  509. TYPED_TEST(AtomicOps, Store)
  510. {
  511. typedef AZStd::atomic<TypeParam> A;
  512. A t;
  513. AZStd::atomic_store(&t, TypeParam(1));
  514. EXPECT_TRUE(t == TypeParam(1));
  515. volatile A vt;
  516. AZStd::atomic_store(&vt, TypeParam(2));
  517. EXPECT_TRUE(vt == TypeParam(2));
  518. }
  519. TYPED_TEST(AtomicOps, StoreExplicit)
  520. {
  521. typedef AZStd::atomic<TypeParam> A;
  522. A t;
  523. AZStd::atomic_store_explicit(&t, TypeParam(1), AZStd::memory_order_seq_cst);
  524. EXPECT_TRUE(t == TypeParam(1));
  525. volatile A vt;
  526. AZStd::atomic_store_explicit(&vt, TypeParam(2), AZStd::memory_order_seq_cst);
  527. EXPECT_TRUE(vt == TypeParam(2));
  528. }
  529. TEST_F(Atomics, AtomicVarInit)
  530. {
  531. AZStd::atomic<int> v = AZ_ATOMIC_VAR_INIT(5);
  532. EXPECT_TRUE(v == 5);
  533. }
  534. template <class Tp>
  535. void test_ctor() {
  536. typedef AZStd::atomic<Tp> Atomic;
  537. Tp t(42);
  538. {
  539. Atomic a(t);
  540. EXPECT_TRUE(a == t);
  541. }
  542. {
  543. Atomic a{ t };
  544. EXPECT_TRUE(a == t);
  545. }
  546. {
  547. Atomic a = AZ_ATOMIC_VAR_INIT(t);
  548. EXPECT_TRUE(a == t);
  549. }
  550. }
  551. TEST_F(Atomics, IntegralCtor)
  552. {
  553. test_ctor<int>();
  554. }
  555. TEST_F(Atomics, UserCtor)
  556. {
  557. test_ctor<IntWrapper>();
  558. }
  559. TEST_F(Atomics, SignalFence)
  560. {
  561. AZStd::atomic_signal_fence(AZStd::memory_order_seq_cst);
  562. }
  563. TEST_F(Atomics, ThreadFence)
  564. {
  565. AZStd::atomic_thread_fence(AZStd::memory_order_seq_cst);
  566. }
  567. TEST_F(Atomics, AtomicFlagClear)
  568. {
  569. {
  570. AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  571. f.test_and_set();
  572. atomic_flag_clear(&f);
  573. EXPECT_TRUE(f.test_and_set() == 0);
  574. }
  575. {
  576. volatile AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  577. f.test_and_set();
  578. atomic_flag_clear(&f);
  579. EXPECT_TRUE(f.test_and_set() == 0);
  580. }
  581. }
  582. TEST_F(Atomics, AtomicFlagClearExplicit)
  583. {
  584. {
  585. AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  586. f.test_and_set();
  587. atomic_flag_clear_explicit(&f, AZStd::memory_order_relaxed);
  588. EXPECT_TRUE(f.test_and_set() == 0);
  589. }
  590. {
  591. AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  592. f.test_and_set();
  593. atomic_flag_clear_explicit(&f, AZStd::memory_order_release);
  594. EXPECT_TRUE(f.test_and_set() == 0);
  595. }
  596. {
  597. AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  598. f.test_and_set();
  599. atomic_flag_clear_explicit(&f, AZStd::memory_order_seq_cst);
  600. EXPECT_TRUE(f.test_and_set() == 0);
  601. }
  602. {
  603. volatile AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  604. f.test_and_set();
  605. atomic_flag_clear_explicit(&f, AZStd::memory_order_relaxed);
  606. EXPECT_TRUE(f.test_and_set() == 0);
  607. }
  608. {
  609. volatile AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  610. f.test_and_set();
  611. atomic_flag_clear_explicit(&f, AZStd::memory_order_release);
  612. EXPECT_TRUE(f.test_and_set() == 0);
  613. }
  614. {
  615. volatile AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  616. f.test_and_set();
  617. atomic_flag_clear_explicit(&f, AZStd::memory_order_seq_cst);
  618. EXPECT_TRUE(f.test_and_set() == 0);
  619. }
  620. }
  621. TEST_F(Atomics, AtomicFlagTestAndSet)
  622. {
  623. {
  624. AZStd::atomic_flag f;
  625. f.clear();
  626. EXPECT_TRUE(atomic_flag_test_and_set(&f) == 0);
  627. EXPECT_TRUE(f.test_and_set() == 1);
  628. }
  629. {
  630. volatile AZStd::atomic_flag f;
  631. f.clear();
  632. EXPECT_TRUE(atomic_flag_test_and_set(&f) == 0);
  633. EXPECT_TRUE(f.test_and_set() == 1);
  634. }
  635. }
  636. TEST_F(Atomics, AtomicFlagTestAndSetExplicit)
  637. {
  638. {
  639. AZStd::atomic_flag f;
  640. f.clear();
  641. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_relaxed) == 0);
  642. EXPECT_TRUE(f.test_and_set() == 1);
  643. }
  644. {
  645. AZStd::atomic_flag f;
  646. f.clear();
  647. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_consume) == 0);
  648. EXPECT_TRUE(f.test_and_set() == 1);
  649. }
  650. {
  651. AZStd::atomic_flag f;
  652. f.clear();
  653. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_acquire) == 0);
  654. EXPECT_TRUE(f.test_and_set() == 1);
  655. }
  656. {
  657. AZStd::atomic_flag f;
  658. f.clear();
  659. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_release) == 0);
  660. EXPECT_TRUE(f.test_and_set() == 1);
  661. }
  662. {
  663. AZStd::atomic_flag f;
  664. f.clear();
  665. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_acq_rel) == 0);
  666. EXPECT_TRUE(f.test_and_set() == 1);
  667. }
  668. {
  669. AZStd::atomic_flag f;
  670. f.clear();
  671. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_seq_cst) == 0);
  672. EXPECT_TRUE(f.test_and_set() == 1);
  673. }
  674. {
  675. volatile AZStd::atomic_flag f;
  676. f.clear();
  677. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_relaxed) == 0);
  678. EXPECT_TRUE(f.test_and_set() == 1);
  679. }
  680. {
  681. volatile AZStd::atomic_flag f;
  682. f.clear();
  683. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_consume) == 0);
  684. EXPECT_TRUE(f.test_and_set() == 1);
  685. }
  686. {
  687. volatile AZStd::atomic_flag f;
  688. f.clear();
  689. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_acquire) == 0);
  690. EXPECT_TRUE(f.test_and_set() == 1);
  691. }
  692. {
  693. volatile AZStd::atomic_flag f;
  694. f.clear();
  695. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_release) == 0);
  696. EXPECT_TRUE(f.test_and_set() == 1);
  697. }
  698. {
  699. volatile AZStd::atomic_flag f;
  700. f.clear();
  701. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_acq_rel) == 0);
  702. EXPECT_TRUE(f.test_and_set() == 1);
  703. }
  704. {
  705. volatile AZStd::atomic_flag f;
  706. f.clear();
  707. EXPECT_TRUE(atomic_flag_test_and_set_explicit(&f, AZStd::memory_order_seq_cst) == 0);
  708. EXPECT_TRUE(f.test_and_set() == 1);
  709. }
  710. }
  711. TEST_F(Atomics, AtomicFlagClearCombinations)
  712. {
  713. {
  714. AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  715. f.test_and_set();
  716. f.clear();
  717. EXPECT_TRUE(f.test_and_set() == 0);
  718. }
  719. {
  720. AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  721. f.test_and_set();
  722. f.clear(AZStd::memory_order_relaxed);
  723. EXPECT_TRUE(f.test_and_set() == 0);
  724. }
  725. {
  726. AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  727. f.test_and_set();
  728. f.clear(AZStd::memory_order_release);
  729. EXPECT_TRUE(f.test_and_set() == 0);
  730. }
  731. {
  732. AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  733. f.test_and_set();
  734. f.clear(AZStd::memory_order_seq_cst);
  735. EXPECT_TRUE(f.test_and_set() == 0);
  736. }
  737. {
  738. volatile AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  739. f.test_and_set();
  740. f.clear();
  741. EXPECT_TRUE(f.test_and_set() == 0);
  742. }
  743. {
  744. volatile AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  745. f.test_and_set();
  746. f.clear(AZStd::memory_order_relaxed);
  747. EXPECT_TRUE(f.test_and_set() == 0);
  748. }
  749. {
  750. volatile AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  751. f.test_and_set();
  752. f.clear(AZStd::memory_order_release);
  753. EXPECT_TRUE(f.test_and_set() == 0);
  754. }
  755. {
  756. volatile AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  757. f.test_and_set();
  758. f.clear(AZStd::memory_order_seq_cst);
  759. EXPECT_TRUE(f.test_and_set() == 0);
  760. }
  761. }
  762. TEST_F(Atomics, AtomicFlagDefault)
  763. {
  764. AZStd::atomic_flag f;
  765. f.clear();
  766. EXPECT_TRUE(f.test_and_set() == 0);
  767. {
  768. typedef AZStd::atomic_flag A;
  769. alignas(A) char storage[sizeof(A)] = { 1 };
  770. A& zero = *new (storage) A();
  771. EXPECT_TRUE(!zero.test_and_set());
  772. zero.~A();
  773. }
  774. }
  775. TEST_F(Atomics, AtomicFlagInit)
  776. {
  777. AZStd::atomic_flag f = AZ_ATOMIC_FLAG_INIT;
  778. EXPECT_TRUE(f.test_and_set() == 0);
  779. }
  780. TEST_F(Atomics, AtomicFlagTestAndSetCombinations)
  781. {
  782. {
  783. AZStd::atomic_flag f;
  784. f.clear();
  785. EXPECT_TRUE(f.test_and_set() == 0);
  786. EXPECT_TRUE(f.test_and_set() == 1);
  787. }
  788. {
  789. AZStd::atomic_flag f;
  790. f.clear();
  791. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_relaxed) == 0);
  792. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_relaxed) == 1);
  793. }
  794. {
  795. AZStd::atomic_flag f;
  796. f.clear();
  797. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_consume) == 0);
  798. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_consume) == 1);
  799. }
  800. {
  801. AZStd::atomic_flag f;
  802. f.clear();
  803. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_acquire) == 0);
  804. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_acquire) == 1);
  805. }
  806. {
  807. AZStd::atomic_flag f;
  808. f.clear();
  809. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_release) == 0);
  810. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_release) == 1);
  811. }
  812. {
  813. AZStd::atomic_flag f;
  814. f.clear();
  815. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_acq_rel) == 0);
  816. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_acq_rel) == 1);
  817. }
  818. {
  819. AZStd::atomic_flag f;
  820. f.clear();
  821. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_seq_cst) == 0);
  822. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_seq_cst) == 1);
  823. }
  824. {
  825. volatile AZStd::atomic_flag f;
  826. f.clear();
  827. EXPECT_TRUE(f.test_and_set() == 0);
  828. EXPECT_TRUE(f.test_and_set() == 1);
  829. }
  830. {
  831. volatile AZStd::atomic_flag f;
  832. f.clear();
  833. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_relaxed) == 0);
  834. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_relaxed) == 1);
  835. }
  836. {
  837. volatile AZStd::atomic_flag f;
  838. f.clear();
  839. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_consume) == 0);
  840. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_consume) == 1);
  841. }
  842. {
  843. volatile AZStd::atomic_flag f;
  844. f.clear();
  845. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_acquire) == 0);
  846. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_acquire) == 1);
  847. }
  848. {
  849. volatile AZStd::atomic_flag f;
  850. f.clear();
  851. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_release) == 0);
  852. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_release) == 1);
  853. }
  854. {
  855. volatile AZStd::atomic_flag f;
  856. f.clear();
  857. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_acq_rel) == 0);
  858. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_acq_rel) == 1);
  859. }
  860. {
  861. volatile AZStd::atomic_flag f;
  862. f.clear();
  863. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_seq_cst) == 0);
  864. EXPECT_TRUE(f.test_and_set(AZStd::memory_order_seq_cst) == 1);
  865. }
  866. }
  867. TEST_F(Atomics, ValidateLockFreeMacros)
  868. {
  869. EXPECT_TRUE(AZ_ATOMIC_CHAR_LOCK_FREE == 0 ||
  870. AZ_ATOMIC_CHAR_LOCK_FREE == 1 ||
  871. AZ_ATOMIC_CHAR_LOCK_FREE == 2);
  872. EXPECT_TRUE(AZ_ATOMIC_CHAR16_T_LOCK_FREE == 0 ||
  873. AZ_ATOMIC_CHAR16_T_LOCK_FREE == 1 ||
  874. AZ_ATOMIC_CHAR16_T_LOCK_FREE == 2);
  875. EXPECT_TRUE(AZ_ATOMIC_CHAR32_T_LOCK_FREE == 0 ||
  876. AZ_ATOMIC_CHAR32_T_LOCK_FREE == 1 ||
  877. AZ_ATOMIC_CHAR32_T_LOCK_FREE == 2);
  878. EXPECT_TRUE(AZ_ATOMIC_WCHAR_T_LOCK_FREE == 0 ||
  879. AZ_ATOMIC_WCHAR_T_LOCK_FREE == 1 ||
  880. AZ_ATOMIC_WCHAR_T_LOCK_FREE == 2);
  881. EXPECT_TRUE(AZ_ATOMIC_SHORT_LOCK_FREE == 0 ||
  882. AZ_ATOMIC_SHORT_LOCK_FREE == 1 ||
  883. AZ_ATOMIC_SHORT_LOCK_FREE == 2);
  884. EXPECT_TRUE(AZ_ATOMIC_INT_LOCK_FREE == 0 ||
  885. AZ_ATOMIC_INT_LOCK_FREE == 1 ||
  886. AZ_ATOMIC_INT_LOCK_FREE == 2);
  887. EXPECT_TRUE(AZ_ATOMIC_LONG_LOCK_FREE == 0 ||
  888. AZ_ATOMIC_LONG_LOCK_FREE == 1 ||
  889. AZ_ATOMIC_LONG_LOCK_FREE == 2);
  890. EXPECT_TRUE(AZ_ATOMIC_LLONG_LOCK_FREE == 0 ||
  891. AZ_ATOMIC_LLONG_LOCK_FREE == 1 ||
  892. AZ_ATOMIC_LLONG_LOCK_FREE == 2);
  893. }
  894. TEST_F(Atomics, KillDependency)
  895. {
  896. EXPECT_TRUE(AZStd::kill_dependency(5) == 5);
  897. EXPECT_TRUE(AZStd::kill_dependency(-5.5) == -5.5);
  898. }
  899. TEST_F(Atomics, ValidateMemoryOrder)
  900. {
  901. EXPECT_TRUE(AZStd::memory_order_relaxed == 0);
  902. EXPECT_TRUE(AZStd::memory_order_consume == 1);
  903. EXPECT_TRUE(AZStd::memory_order_acquire == 2);
  904. EXPECT_TRUE(AZStd::memory_order_release == 3);
  905. EXPECT_TRUE(AZStd::memory_order_acq_rel == 4);
  906. EXPECT_TRUE(AZStd::memory_order_seq_cst == 5);
  907. AZStd::memory_order o = AZStd::memory_order_seq_cst;
  908. EXPECT_TRUE(o == 5);
  909. }
  910. template <class A, class T>
  911. void validate_atomic_ptr()
  912. {
  913. typedef typename AZStd::remove_pointer<T>::type X;
  914. A obj(T(0));
  915. bool b0 = obj.is_lock_free();
  916. ((void)b0); // mark as unused
  917. EXPECT_TRUE(obj == T(nullptr));
  918. AZStd::atomic_init(&obj, T(1));
  919. EXPECT_TRUE(obj == T(1));
  920. AZStd::atomic_init(&obj, T(2));
  921. EXPECT_TRUE(obj == T(2));
  922. obj.store(T(0));
  923. EXPECT_TRUE(obj == T(nullptr));
  924. obj.store(T(1), AZStd::memory_order_release);
  925. EXPECT_TRUE(obj == T(1));
  926. EXPECT_TRUE(obj.load() == T(1));
  927. EXPECT_TRUE(obj.load(AZStd::memory_order_acquire) == T(1));
  928. EXPECT_TRUE(obj.exchange(T(2)) == T(1));
  929. EXPECT_TRUE(obj == T(2));
  930. EXPECT_TRUE(obj.exchange(T(3), AZStd::memory_order_relaxed) == T(2));
  931. EXPECT_TRUE(obj == T(3));
  932. T x = obj;
  933. EXPECT_TRUE(cmpxchg_weak_loop(obj, x, T(2)) == true);
  934. EXPECT_TRUE(obj == T(2));
  935. EXPECT_TRUE(x == T(3));
  936. EXPECT_TRUE(obj.compare_exchange_weak(x, T(1)) == false);
  937. EXPECT_TRUE(obj == T(2));
  938. EXPECT_TRUE(x == T(2));
  939. x = T(2);
  940. EXPECT_TRUE(obj.compare_exchange_strong(x, T(1)) == true);
  941. EXPECT_TRUE(obj == T(1));
  942. EXPECT_TRUE(x == T(2));
  943. EXPECT_TRUE(obj.compare_exchange_strong(x, T(nullptr)) == false);
  944. EXPECT_TRUE(obj == T(1));
  945. EXPECT_TRUE(x == T(1));
  946. EXPECT_TRUE((obj = T(nullptr)) == T(nullptr));
  947. EXPECT_TRUE(obj == T(nullptr));
  948. obj = T(2 * sizeof(X));
  949. EXPECT_TRUE((obj += AZStd::ptrdiff_t(3)) == T(5 * sizeof(X)));
  950. EXPECT_TRUE(obj == T(5 * sizeof(X)));
  951. EXPECT_TRUE((obj -= AZStd::ptrdiff_t(3)) == T(2 * sizeof(X)));
  952. EXPECT_TRUE(obj == T(2 * sizeof(X)));
  953. {
  954. alignas(A) char storage[sizeof(A)] = { 23 };
  955. A& zero = *new (storage) A();
  956. EXPECT_TRUE(zero == T(nullptr));
  957. zero.~A();
  958. }
  959. }
  960. template <class A, class T>
  961. void validate_atomic_ptr_variations()
  962. {
  963. validate_atomic_ptr<A, T>();
  964. validate_atomic_ptr<volatile A, T>();
  965. }
  966. TEST_F(Atomics, AtomicPtrVariations)
  967. {
  968. validate_atomic_ptr_variations<AZStd::atomic<int*>, int*>();
  969. }
  970. TEST_F(Atomics, AtomicBoolFullSuite)
  971. {
  972. {
  973. volatile AZStd::atomic<bool> obj(true);
  974. EXPECT_TRUE(obj == true);
  975. AZStd::atomic_init(&obj, false);
  976. EXPECT_TRUE(obj == false);
  977. AZStd::atomic_init(&obj, true);
  978. EXPECT_TRUE(obj == true);
  979. bool b0 = obj.is_lock_free();
  980. (void)b0; // to placate scan-build
  981. obj.store(false);
  982. EXPECT_TRUE(obj == false);
  983. obj.store(true, AZStd::memory_order_release);
  984. EXPECT_TRUE(obj == true);
  985. EXPECT_TRUE(obj.load() == true);
  986. EXPECT_TRUE(obj.load(AZStd::memory_order_acquire) == true);
  987. EXPECT_TRUE(obj.exchange(false) == true);
  988. EXPECT_TRUE(obj == false);
  989. EXPECT_TRUE(obj.exchange(true, AZStd::memory_order_relaxed) == false);
  990. EXPECT_TRUE(obj == true);
  991. bool x = obj;
  992. EXPECT_TRUE(cmpxchg_weak_loop(obj, x, false) == true);
  993. EXPECT_TRUE(obj == false);
  994. EXPECT_TRUE(x == true);
  995. EXPECT_TRUE(obj.compare_exchange_weak(x, true,
  996. AZStd::memory_order_seq_cst) == false);
  997. EXPECT_TRUE(obj == false);
  998. EXPECT_TRUE(x == false);
  999. obj.store(true);
  1000. x = true;
  1001. EXPECT_TRUE(cmpxchg_weak_loop(obj, x, false,
  1002. AZStd::memory_order_seq_cst,
  1003. AZStd::memory_order_seq_cst) == true);
  1004. EXPECT_TRUE(obj == false);
  1005. EXPECT_TRUE(x == true);
  1006. x = true;
  1007. obj.store(true);
  1008. EXPECT_TRUE(obj.compare_exchange_strong(x, false) == true);
  1009. EXPECT_TRUE(obj == false);
  1010. EXPECT_TRUE(x == true);
  1011. EXPECT_TRUE(obj.compare_exchange_strong(x, true,
  1012. AZStd::memory_order_seq_cst) == false);
  1013. EXPECT_TRUE(obj == false);
  1014. EXPECT_TRUE(x == false);
  1015. x = true;
  1016. obj.store(true);
  1017. EXPECT_TRUE(obj.compare_exchange_strong(x, false,
  1018. AZStd::memory_order_seq_cst,
  1019. AZStd::memory_order_seq_cst) == true);
  1020. EXPECT_TRUE(obj == false);
  1021. EXPECT_TRUE(x == true);
  1022. EXPECT_TRUE((obj = false) == false);
  1023. EXPECT_TRUE(obj == false);
  1024. EXPECT_TRUE((obj = true) == true);
  1025. EXPECT_TRUE(obj == true);
  1026. }
  1027. {
  1028. AZStd::atomic<bool> obj(true);
  1029. EXPECT_TRUE(obj == true);
  1030. AZStd::atomic_init(&obj, false);
  1031. EXPECT_TRUE(obj == false);
  1032. AZStd::atomic_init(&obj, true);
  1033. EXPECT_TRUE(obj == true);
  1034. bool b0 = obj.is_lock_free();
  1035. (void)b0; // to placate scan-build
  1036. obj.store(false);
  1037. EXPECT_TRUE(obj == false);
  1038. obj.store(true, AZStd::memory_order_release);
  1039. EXPECT_TRUE(obj == true);
  1040. EXPECT_TRUE(obj.load() == true);
  1041. EXPECT_TRUE(obj.load(AZStd::memory_order_acquire) == true);
  1042. EXPECT_TRUE(obj.exchange(false) == true);
  1043. EXPECT_TRUE(obj == false);
  1044. EXPECT_TRUE(obj.exchange(true, AZStd::memory_order_relaxed) == false);
  1045. EXPECT_TRUE(obj == true);
  1046. bool x = obj;
  1047. EXPECT_TRUE(cmpxchg_weak_loop(obj, x, false) == true);
  1048. EXPECT_TRUE(obj == false);
  1049. EXPECT_TRUE(x == true);
  1050. EXPECT_TRUE(obj.compare_exchange_weak(x, true,
  1051. AZStd::memory_order_seq_cst) == false);
  1052. EXPECT_TRUE(obj == false);
  1053. EXPECT_TRUE(x == false);
  1054. obj.store(true);
  1055. x = true;
  1056. EXPECT_TRUE(cmpxchg_weak_loop(obj, x, false,
  1057. AZStd::memory_order_seq_cst,
  1058. AZStd::memory_order_seq_cst) == true);
  1059. EXPECT_TRUE(obj == false);
  1060. EXPECT_TRUE(x == true);
  1061. x = true;
  1062. obj.store(true);
  1063. EXPECT_TRUE(obj.compare_exchange_strong(x, false) == true);
  1064. EXPECT_TRUE(obj == false);
  1065. EXPECT_TRUE(x == true);
  1066. EXPECT_TRUE(obj.compare_exchange_strong(x, true,
  1067. AZStd::memory_order_seq_cst) == false);
  1068. EXPECT_TRUE(obj == false);
  1069. EXPECT_TRUE(x == false);
  1070. x = true;
  1071. obj.store(true);
  1072. EXPECT_TRUE(obj.compare_exchange_strong(x, false,
  1073. AZStd::memory_order_seq_cst,
  1074. AZStd::memory_order_seq_cst) == true);
  1075. EXPECT_TRUE(obj == false);
  1076. EXPECT_TRUE(x == true);
  1077. EXPECT_TRUE((obj = false) == false);
  1078. EXPECT_TRUE(obj == false);
  1079. EXPECT_TRUE((obj = true) == true);
  1080. EXPECT_TRUE(obj == true);
  1081. }
  1082. {
  1083. AZStd::atomic_bool obj(true);
  1084. EXPECT_TRUE(obj == true);
  1085. AZStd::atomic_init(&obj, false);
  1086. EXPECT_TRUE(obj == false);
  1087. AZStd::atomic_init(&obj, true);
  1088. EXPECT_TRUE(obj == true);
  1089. bool b0 = obj.is_lock_free();
  1090. (void)b0; // to placate scan-build
  1091. obj.store(false);
  1092. EXPECT_TRUE(obj == false);
  1093. obj.store(true, AZStd::memory_order_release);
  1094. EXPECT_TRUE(obj == true);
  1095. EXPECT_TRUE(obj.load() == true);
  1096. EXPECT_TRUE(obj.load(AZStd::memory_order_acquire) == true);
  1097. EXPECT_TRUE(obj.exchange(false) == true);
  1098. EXPECT_TRUE(obj == false);
  1099. EXPECT_TRUE(obj.exchange(true, AZStd::memory_order_relaxed) == false);
  1100. EXPECT_TRUE(obj == true);
  1101. bool x = obj;
  1102. EXPECT_TRUE(cmpxchg_weak_loop(obj, x, false) == true);
  1103. EXPECT_TRUE(obj == false);
  1104. EXPECT_TRUE(x == true);
  1105. EXPECT_TRUE(obj.compare_exchange_weak(x, true,
  1106. AZStd::memory_order_seq_cst) == false);
  1107. EXPECT_TRUE(obj == false);
  1108. EXPECT_TRUE(x == false);
  1109. obj.store(true);
  1110. x = true;
  1111. EXPECT_TRUE(cmpxchg_weak_loop(obj, x, false,
  1112. AZStd::memory_order_seq_cst,
  1113. AZStd::memory_order_seq_cst) == true);
  1114. EXPECT_TRUE(obj == false);
  1115. EXPECT_TRUE(x == true);
  1116. x = true;
  1117. obj.store(true);
  1118. EXPECT_TRUE(obj.compare_exchange_strong(x, false) == true);
  1119. EXPECT_TRUE(obj == false);
  1120. EXPECT_TRUE(x == true);
  1121. EXPECT_TRUE(obj.compare_exchange_strong(x, true,
  1122. AZStd::memory_order_seq_cst) == false);
  1123. EXPECT_TRUE(obj == false);
  1124. EXPECT_TRUE(x == false);
  1125. x = true;
  1126. obj.store(true);
  1127. EXPECT_TRUE(obj.compare_exchange_strong(x, false,
  1128. AZStd::memory_order_seq_cst,
  1129. AZStd::memory_order_seq_cst) == true);
  1130. EXPECT_TRUE(obj == false);
  1131. EXPECT_TRUE(x == true);
  1132. EXPECT_TRUE((obj = false) == false);
  1133. EXPECT_TRUE(obj == false);
  1134. EXPECT_TRUE((obj = true) == true);
  1135. EXPECT_TRUE(obj == true);
  1136. }
  1137. {
  1138. typedef AZStd::atomic<bool> A;
  1139. alignas(A) char storage[sizeof(A)] = { 1 };
  1140. A& zero = *new (storage) A();
  1141. EXPECT_TRUE(zero == false);
  1142. zero.~A();
  1143. }
  1144. }
  1145. template <class A, class T>
  1146. void test_atomic_integral()
  1147. {
  1148. A obj(T(0));
  1149. EXPECT_TRUE(obj == T(0));
  1150. AZStd::atomic_init(&obj, T(1));
  1151. EXPECT_TRUE(obj == T(1));
  1152. AZStd::atomic_init(&obj, T(2));
  1153. EXPECT_TRUE(obj == T(2));
  1154. bool b0 = obj.is_lock_free();
  1155. ((void)b0); // mark as unused
  1156. obj.store(T(0));
  1157. EXPECT_TRUE(obj == T(0));
  1158. obj.store(T(1), AZStd::memory_order_release);
  1159. EXPECT_TRUE(obj == T(1));
  1160. EXPECT_TRUE(obj.load() == T(1));
  1161. EXPECT_TRUE(obj.load(AZStd::memory_order_acquire) == T(1));
  1162. EXPECT_TRUE(obj.exchange(T(2)) == T(1));
  1163. EXPECT_TRUE(obj == T(2));
  1164. EXPECT_TRUE(obj.exchange(T(3), AZStd::memory_order_relaxed) == T(2));
  1165. EXPECT_TRUE(obj == T(3));
  1166. T x = obj;
  1167. EXPECT_TRUE(cmpxchg_weak_loop(obj, x, T(2)) == true);
  1168. EXPECT_TRUE(obj == T(2));
  1169. EXPECT_TRUE(x == T(3));
  1170. EXPECT_TRUE(obj.compare_exchange_weak(x, T(1)) == false);
  1171. EXPECT_TRUE(obj == T(2));
  1172. EXPECT_TRUE(x == T(2));
  1173. x = T(2);
  1174. EXPECT_TRUE(obj.compare_exchange_strong(x, T(1)) == true);
  1175. EXPECT_TRUE(obj == T(1));
  1176. EXPECT_TRUE(x == T(2));
  1177. EXPECT_TRUE(obj.compare_exchange_strong(x, T(0)) == false);
  1178. EXPECT_TRUE(obj == T(1));
  1179. EXPECT_TRUE(x == T(1));
  1180. EXPECT_TRUE((obj = T(0)) == T(0));
  1181. EXPECT_TRUE(obj == T(0));
  1182. EXPECT_TRUE(obj++ == T(0));
  1183. EXPECT_TRUE(obj == T(1));
  1184. EXPECT_TRUE(++obj == T(2));
  1185. EXPECT_TRUE(obj == T(2));
  1186. EXPECT_TRUE(--obj == T(1));
  1187. EXPECT_TRUE(obj == T(1));
  1188. EXPECT_TRUE(obj-- == T(1));
  1189. EXPECT_TRUE(obj == T(0));
  1190. obj = T(2);
  1191. EXPECT_TRUE((obj += T(3)) == T(5));
  1192. EXPECT_TRUE(obj == T(5));
  1193. EXPECT_TRUE((obj -= T(3)) == T(2));
  1194. EXPECT_TRUE(obj == T(2));
  1195. EXPECT_TRUE((obj |= T(5)) == T(7));
  1196. EXPECT_TRUE(obj == T(7));
  1197. EXPECT_TRUE((obj &= T(0xF)) == T(7));
  1198. EXPECT_TRUE(obj == T(7));
  1199. EXPECT_TRUE((obj ^= T(0xF)) == T(8));
  1200. EXPECT_TRUE(obj == T(8));
  1201. {
  1202. alignas(A) char storage[sizeof(A)] = { 23 };
  1203. A& zero = *new (storage) A();
  1204. EXPECT_TRUE(zero == 0);
  1205. zero.~A();
  1206. }
  1207. }
  1208. template <class A, class T>
  1209. void test_atomic_integral_variations()
  1210. {
  1211. test_atomic_integral<A, T>();
  1212. test_atomic_integral<volatile A, T>();
  1213. }
  1214. TEST_F(Atomics, AtomicIntegralsFullSuite)
  1215. {
  1216. // NOTE: wchar_t is not integral in our impl, and schar was removed
  1217. test_atomic_integral_variations<AZStd::atomic_char, char>();
  1218. test_atomic_integral_variations<AZStd::atomic_uchar, unsigned char>();
  1219. test_atomic_integral_variations<AZStd::atomic_short, short>();
  1220. test_atomic_integral_variations<AZStd::atomic_ushort, unsigned short>();
  1221. test_atomic_integral_variations<AZStd::atomic_int, int>();
  1222. test_atomic_integral_variations<AZStd::atomic_uint, unsigned int>();
  1223. test_atomic_integral_variations<AZStd::atomic_long, long>();
  1224. test_atomic_integral_variations<AZStd::atomic_ulong, unsigned long>();
  1225. test_atomic_integral_variations<AZStd::atomic_llong, long long>();
  1226. test_atomic_integral_variations<AZStd::atomic_ullong, unsigned long long>();
  1227. test_atomic_integral_variations<AZStd::atomic_size_t, size_t>();
  1228. test_atomic_integral_variations<AZStd::atomic_ptrdiff_t, ptrdiff_t>();
  1229. test_atomic_integral_variations<AZStd::atomic_int8_t, int8_t>();
  1230. test_atomic_integral_variations<AZStd::atomic_uint8_t, uint8_t>();
  1231. test_atomic_integral_variations<AZStd::atomic_int16_t, int16_t>();
  1232. test_atomic_integral_variations<AZStd::atomic_uint16_t, uint16_t>();
  1233. test_atomic_integral_variations<AZStd::atomic_int32_t, int32_t>();
  1234. test_atomic_integral_variations<AZStd::atomic_uint32_t, uint32_t>();
  1235. test_atomic_integral_variations<AZStd::atomic_int64_t, int64_t>();
  1236. test_atomic_integral_variations<AZStd::atomic_uint64_t, uint64_t>();
  1237. }
  1238. }