ConcurrentContainers.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  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. #include "UserTypes.h"
  9. #include <AzCore/std/parallel/containers/concurrent_fixed_unordered_set.h>
  10. #include <AzCore/std/parallel/containers/concurrent_fixed_unordered_map.h>
  11. #include <AzCore/std/parallel/containers/concurrent_unordered_map.h>
  12. #include <AzCore/std/parallel/containers/concurrent_unordered_set.h>
  13. #include <AzCore/std/parallel/containers/concurrent_vector.h>
  14. #include <AzCore/std/parallel/thread.h>
  15. #include <AzCore/std/functional.h>
  16. #include <AzCore/std/smart_ptr/unique_ptr.h>
  17. namespace UnitTest
  18. {
  19. using namespace AZStd;
  20. using namespace UnitTestInternal;
  21. template<typename Set>
  22. class ConcurrentUnorderedSetTestBase
  23. : public LeakDetectionFixture
  24. {
  25. public:
  26. void run()
  27. {
  28. Set set;
  29. //insert
  30. AZ_TEST_ASSERT(set.empty());
  31. AZ_TEST_ASSERT(set.size() == 0);
  32. AZ_TEST_ASSERT(set.insert(10));
  33. AZ_TEST_ASSERT(!set.empty());
  34. AZ_TEST_ASSERT(set.size() == 1);
  35. AZ_TEST_ASSERT(set.insert(20));
  36. AZ_TEST_ASSERT(set.size() == 2);
  37. AZ_TEST_ASSERT(set.insert(30));
  38. AZ_TEST_ASSERT(set.size() == 3);
  39. AZ_TEST_ASSERT(!set.insert(20)); //not multiset
  40. AZ_TEST_ASSERT(set.size() == 3);
  41. //find
  42. AZ_TEST_ASSERT(set.find(10));
  43. AZ_TEST_ASSERT(!set.find(40));
  44. //erase
  45. AZ_TEST_ASSERT(set.erase(10) == 1);
  46. AZ_TEST_ASSERT(set.size() == 2);
  47. AZ_TEST_ASSERT(set.erase(10) == 0);
  48. AZ_TEST_ASSERT(set.size() == 2);
  49. AZ_TEST_ASSERT(set.erase(100) == 0);
  50. AZ_TEST_ASSERT(set.size() == 2);
  51. //erase_one
  52. AZ_TEST_ASSERT(set.erase_one(20));
  53. AZ_TEST_ASSERT(set.size() == 1);
  54. AZ_TEST_ASSERT(set.erase_one(30));
  55. AZ_TEST_ASSERT(set.size() == 0);
  56. AZ_TEST_ASSERT(set.empty());
  57. //clear
  58. set.insert(10);
  59. AZ_TEST_ASSERT(!set.empty());
  60. set.clear();
  61. AZ_TEST_ASSERT(set.empty());
  62. AZ_TEST_ASSERT(set.erase(10) == 0);
  63. //assignment
  64. set.insert(10);
  65. set.insert(20);
  66. set.insert(30);
  67. Set set2(set);
  68. AZ_TEST_ASSERT(set2.size() == 3);
  69. AZ_TEST_ASSERT(set2.find(20));
  70. Set set3;
  71. set3 = set;
  72. AZ_TEST_ASSERT(set3.size() == 3);
  73. AZ_TEST_ASSERT(set3.find(20));
  74. set.erase(10);
  75. AZ_TEST_ASSERT(set.size() == 2);
  76. set.swap(set3);
  77. AZ_TEST_ASSERT(set.size() == 3);
  78. AZ_TEST_ASSERT(set3.size() == 2);
  79. {
  80. m_failures = 0;
  81. AZStd::thread thread0(AZStd::bind(&ConcurrentUnorderedSetTestBase::InsertErase, this, 0));
  82. AZStd::thread thread1(AZStd::bind(&ConcurrentUnorderedSetTestBase::InsertErase, this, 1));
  83. AZStd::thread thread2(AZStd::bind(&ConcurrentUnorderedSetTestBase::InsertErase, this, 2));
  84. AZStd::thread thread3(AZStd::bind(&ConcurrentUnorderedSetTestBase::InsertErase, this, 3));
  85. thread0.join();
  86. thread1.join();
  87. thread2.join();
  88. thread3.join();
  89. AZ_TEST_ASSERT(m_failures == 0);
  90. AZ_TEST_ASSERT(m_set.empty());
  91. }
  92. m_set = Set(); // clear memory
  93. }
  94. private:
  95. #ifdef _DEBUG
  96. static const int NUM_ITERATIONS = 1;
  97. #else
  98. static const int NUM_ITERATIONS = 200;
  99. #endif
  100. static const int NUM_VALUES = 500;
  101. void InsertErase(int id)
  102. {
  103. for (int iter = 0; iter < NUM_ITERATIONS; ++iter)
  104. {
  105. //insert
  106. for (int i = 0; i < NUM_VALUES; ++i)
  107. {
  108. if (!m_set.insert(id * NUM_VALUES + i))
  109. {
  110. ++m_failures;
  111. }
  112. }
  113. //find
  114. for (int i = 0; i < NUM_VALUES; ++i)
  115. {
  116. if (!m_set.find(id * NUM_VALUES + i))
  117. {
  118. ++m_failures;
  119. }
  120. }
  121. //erase
  122. for (int i = 0; i < NUM_VALUES; ++i)
  123. {
  124. if (m_set.erase(id * NUM_VALUES + i) != 1)
  125. {
  126. ++m_failures;
  127. }
  128. }
  129. }
  130. }
  131. Set m_set;
  132. atomic<int> m_failures;
  133. };
  134. typedef ConcurrentUnorderedSetTestBase<concurrent_unordered_set<int> > ConcurrentUnorderedSetTest;
  135. typedef ConcurrentUnorderedSetTestBase<concurrent_fixed_unordered_set<int, 1543, 2100> > ConcurrentFixedUnorderedSetTest;
  136. TEST_F(ConcurrentUnorderedSetTest, Test)
  137. {
  138. run();
  139. }
  140. TEST_F(ConcurrentFixedUnorderedSetTest, Test)
  141. {
  142. run();
  143. }
  144. template<typename Set>
  145. class ConcurrentUnorderedMultiSetTestBase
  146. : public LeakDetectionFixture
  147. {
  148. public:
  149. void run()
  150. {
  151. Set set;
  152. //insert
  153. AZ_TEST_ASSERT(set.empty());
  154. AZ_TEST_ASSERT(set.size() == 0);
  155. AZ_TEST_ASSERT(set.insert(10));
  156. AZ_TEST_ASSERT(!set.empty());
  157. AZ_TEST_ASSERT(set.size() == 1);
  158. AZ_TEST_ASSERT(set.insert(20));
  159. AZ_TEST_ASSERT(set.size() == 2);
  160. AZ_TEST_ASSERT(set.insert(20)); //multiset
  161. AZ_TEST_ASSERT(set.size() == 3);
  162. AZ_TEST_ASSERT(set.insert(30));
  163. AZ_TEST_ASSERT(set.insert(30));
  164. AZ_TEST_ASSERT(set.insert(30));
  165. AZ_TEST_ASSERT(set.size() == 6);
  166. //find
  167. AZ_TEST_ASSERT(set.find(10));
  168. AZ_TEST_ASSERT(set.find(20));
  169. AZ_TEST_ASSERT(!set.find(40));
  170. //erase
  171. AZ_TEST_ASSERT(set.erase(10) == 1);
  172. AZ_TEST_ASSERT(set.size() == 5);
  173. AZ_TEST_ASSERT(set.erase(10) == 0);
  174. AZ_TEST_ASSERT(set.size() == 5);
  175. AZ_TEST_ASSERT(set.erase(100) == 0);
  176. AZ_TEST_ASSERT(set.size() == 5);
  177. AZ_TEST_ASSERT(set.erase(20) == 2);
  178. AZ_TEST_ASSERT(set.size() == 3);
  179. //erase_one
  180. AZ_TEST_ASSERT(set.erase_one(30));
  181. AZ_TEST_ASSERT(set.size() == 2);
  182. AZ_TEST_ASSERT(set.erase(30) == 2);
  183. AZ_TEST_ASSERT(set.size() == 0);
  184. AZ_TEST_ASSERT(set.empty());
  185. //clear
  186. set.insert(10);
  187. AZ_TEST_ASSERT(!set.empty());
  188. set.clear();
  189. AZ_TEST_ASSERT(set.empty());
  190. AZ_TEST_ASSERT(set.erase(10) == 0);
  191. //assignment
  192. set.insert(10);
  193. set.insert(20);
  194. set.insert(30);
  195. Set set2(set);
  196. AZ_TEST_ASSERT(set2.size() == 3);
  197. AZ_TEST_ASSERT(set2.find(20));
  198. Set set3;
  199. set3 = set;
  200. AZ_TEST_ASSERT(set3.size() == 3);
  201. AZ_TEST_ASSERT(set3.find(20));
  202. set.erase(10);
  203. AZ_TEST_ASSERT(set.size() == 2);
  204. set.swap(set3);
  205. AZ_TEST_ASSERT(set.size() == 3);
  206. AZ_TEST_ASSERT(set3.size() == 2);
  207. {
  208. m_failures = 0;
  209. AZStd::thread thread0(AZStd::bind(&ConcurrentUnorderedMultiSetTestBase::InsertErase, this));
  210. AZStd::thread thread1(AZStd::bind(&ConcurrentUnorderedMultiSetTestBase::InsertErase, this));
  211. AZStd::thread thread2(AZStd::bind(&ConcurrentUnorderedMultiSetTestBase::InsertErase, this));
  212. AZStd::thread thread3(AZStd::bind(&ConcurrentUnorderedMultiSetTestBase::InsertErase, this));
  213. thread0.join();
  214. thread1.join();
  215. thread2.join();
  216. thread3.join();
  217. AZ_TEST_ASSERT(m_failures == 0);
  218. AZ_TEST_ASSERT(m_set.empty());
  219. }
  220. m_set = Set(); // clear memory
  221. }
  222. private:
  223. #ifdef _DEBUG
  224. static const int NUM_ITERATIONS = 1;
  225. #else
  226. static const int NUM_ITERATIONS = 200;
  227. #endif
  228. static const int NUM_VALUES = 500;
  229. void InsertErase()
  230. {
  231. for (int iter = 0; iter < NUM_ITERATIONS; ++iter)
  232. {
  233. //insert
  234. for (int i = 0; i < NUM_VALUES; ++i)
  235. {
  236. if (!m_set.insert(i))
  237. {
  238. ++m_failures;
  239. }
  240. }
  241. //find
  242. for (int i = 0; i < NUM_VALUES; ++i)
  243. {
  244. if (!m_set.find(i))
  245. {
  246. ++m_failures;
  247. }
  248. }
  249. //erase
  250. for (int i = 0; i < NUM_VALUES; ++i)
  251. {
  252. if (!m_set.erase_one(i))
  253. {
  254. ++m_failures;
  255. }
  256. }
  257. }
  258. }
  259. Set m_set;
  260. atomic<int> m_failures;
  261. };
  262. typedef ConcurrentUnorderedMultiSetTestBase<concurrent_unordered_multiset<int> > ConcurrentUnorderedMultiSetTest;
  263. typedef ConcurrentUnorderedMultiSetTestBase<concurrent_fixed_unordered_multiset<int, 1543, 2100> > ConcurrentFixedUnorderedMultiSetTest;
  264. TEST_F(ConcurrentUnorderedMultiSetTest, Test)
  265. {
  266. run();
  267. }
  268. TEST_F(ConcurrentFixedUnorderedMultiSetTest, Test)
  269. {
  270. run();
  271. }
  272. template<typename Map>
  273. class ConcurrentUnorderedMapTestBase
  274. : public LeakDetectionFixture
  275. {
  276. public:
  277. void run()
  278. {
  279. Map map;
  280. //insert
  281. AZ_TEST_ASSERT(map.empty());
  282. AZ_TEST_ASSERT(map.size() == 0);
  283. AZ_TEST_ASSERT(map.insert(AZStd::make_pair(10, 11)));
  284. AZ_TEST_ASSERT(!map.empty());
  285. AZ_TEST_ASSERT(map.size() == 1);
  286. AZ_TEST_ASSERT(map.insert(AZStd::make_pair(20, 21)));
  287. AZ_TEST_ASSERT(map.size() == 2);
  288. AZ_TEST_ASSERT(map.insert(AZStd::make_pair(30, 31)));
  289. AZ_TEST_ASSERT(map.size() == 3);
  290. AZ_TEST_ASSERT(!map.insert(AZStd::make_pair(20, 22))); //not multimap
  291. AZ_TEST_ASSERT(map.size() == 3);
  292. //find
  293. AZ_TEST_ASSERT(map.find(10));
  294. AZ_TEST_ASSERT(!map.find(40));
  295. int result = 0;
  296. AZ_TEST_ASSERT(map.find(10, &result));
  297. AZ_TEST_ASSERT(result == 11);
  298. //erase
  299. AZ_TEST_ASSERT(map.erase(10) == 1);
  300. AZ_TEST_ASSERT(map.size() == 2);
  301. AZ_TEST_ASSERT(map.erase(10) == 0);
  302. AZ_TEST_ASSERT(map.size() == 2);
  303. AZ_TEST_ASSERT(map.erase(100) == 0);
  304. AZ_TEST_ASSERT(map.size() == 2);
  305. //erase_one
  306. AZ_TEST_ASSERT(map.erase_one(20));
  307. AZ_TEST_ASSERT(map.size() == 1);
  308. AZ_TEST_ASSERT(map.erase_one(30));
  309. AZ_TEST_ASSERT(map.size() == 0);
  310. AZ_TEST_ASSERT(map.empty());
  311. //clear
  312. map.insert(10);
  313. AZ_TEST_ASSERT(!map.empty());
  314. map.clear();
  315. AZ_TEST_ASSERT(map.empty());
  316. AZ_TEST_ASSERT(map.erase(10) == 0);
  317. //assignment
  318. map.insert(AZStd::make_pair(10, 11));
  319. map.insert(AZStd::make_pair(20, 21));
  320. map.insert(AZStd::make_pair(30, 31));
  321. Map map2(map);
  322. AZ_TEST_ASSERT(map2.size() == 3);
  323. AZ_TEST_ASSERT(map2.find(20));
  324. Map map3;
  325. map3 = map;
  326. AZ_TEST_ASSERT(map3.size() == 3);
  327. AZ_TEST_ASSERT(map3.find(20));
  328. map.erase(10);
  329. AZ_TEST_ASSERT(map.size() == 2);
  330. map.swap(map3);
  331. AZ_TEST_ASSERT(map.size() == 3);
  332. AZ_TEST_ASSERT(map3.size() == 2);
  333. {
  334. m_failures = 0;
  335. AZStd::thread thread0(AZStd::bind(&ConcurrentUnorderedMapTestBase::InsertErase, this, 0));
  336. AZStd::thread thread1(AZStd::bind(&ConcurrentUnorderedMapTestBase::InsertErase, this, 1));
  337. AZStd::thread thread2(AZStd::bind(&ConcurrentUnorderedMapTestBase::InsertErase, this, 2));
  338. AZStd::thread thread3(AZStd::bind(&ConcurrentUnorderedMapTestBase::InsertErase, this, 3));
  339. thread0.join();
  340. thread1.join();
  341. thread2.join();
  342. thread3.join();
  343. AZ_TEST_ASSERT(m_failures == 0);
  344. AZ_TEST_ASSERT(m_map.empty());
  345. }
  346. m_map = Map(); // clear memory
  347. }
  348. private:
  349. #ifdef _DEBUG
  350. static const int NUM_ITERATIONS = 1;
  351. #else
  352. static const int NUM_ITERATIONS = 200;
  353. #endif
  354. static const int NUM_VALUES = 500;
  355. void InsertErase(int id)
  356. {
  357. for (int iter = 0; iter < NUM_ITERATIONS; ++iter)
  358. {
  359. //insert
  360. for (int i = 0; i < NUM_VALUES; ++i)
  361. {
  362. if (!m_map.insert(AZStd::make_pair(id * NUM_VALUES + i, id * NUM_VALUES + i + 1)))
  363. {
  364. ++m_failures;
  365. }
  366. }
  367. //find
  368. for (int i = 0; i < NUM_VALUES; ++i)
  369. {
  370. int result = 0;
  371. if (!m_map.find(id * NUM_VALUES + i, &result))
  372. {
  373. ++m_failures;
  374. }
  375. if (result != id * NUM_VALUES + i + 1)
  376. {
  377. ++m_failures;
  378. }
  379. }
  380. //erase
  381. for (int i = 0; i < NUM_VALUES; ++i)
  382. {
  383. if (m_map.erase(id * NUM_VALUES + i) != 1)
  384. {
  385. ++m_failures;
  386. }
  387. }
  388. }
  389. }
  390. Map m_map;
  391. atomic<int> m_failures;
  392. };
  393. typedef ConcurrentUnorderedMapTestBase<concurrent_unordered_map<int, int> > ConcurrentUnorderedMapTest;
  394. typedef ConcurrentUnorderedMapTestBase<concurrent_fixed_unordered_map<int, int, 1543, 2100> > ConcurrentFixedUnorderedMapTest;
  395. TEST_F(ConcurrentUnorderedMapTest, Test)
  396. {
  397. run();
  398. }
  399. TEST_F(ConcurrentFixedUnorderedMapTest, Test)
  400. {
  401. run();
  402. }
  403. template<typename Map>
  404. class ConcurrentUnorderedMultiMapTestBase
  405. : public LeakDetectionFixture
  406. {
  407. public:
  408. void run()
  409. {
  410. Map map;
  411. //insert
  412. AZ_TEST_ASSERT(map.empty());
  413. AZ_TEST_ASSERT(map.size() == 0);
  414. AZ_TEST_ASSERT(map.insert(AZStd::make_pair(10, 11)));
  415. AZ_TEST_ASSERT(!map.empty());
  416. AZ_TEST_ASSERT(map.size() == 1);
  417. AZ_TEST_ASSERT(map.insert(AZStd::make_pair(20, 21)));
  418. AZ_TEST_ASSERT(map.size() == 2);
  419. AZ_TEST_ASSERT(map.insert(AZStd::make_pair(20, 22))); //multimap
  420. AZ_TEST_ASSERT(map.size() == 3);
  421. AZ_TEST_ASSERT(map.insert(AZStd::make_pair(30, 31)));
  422. AZ_TEST_ASSERT(map.insert(AZStd::make_pair(30, 32)));
  423. AZ_TEST_ASSERT(map.insert(AZStd::make_pair(30, 33)));
  424. AZ_TEST_ASSERT(map.size() == 6);
  425. //find
  426. AZ_TEST_ASSERT(map.find(10));
  427. AZ_TEST_ASSERT(map.find(20));
  428. AZ_TEST_ASSERT(!map.find(40));
  429. int result = 0;
  430. AZ_TEST_ASSERT(map.find(10, &result));
  431. AZ_TEST_ASSERT(result == 11);
  432. //erase
  433. AZ_TEST_ASSERT(map.erase(10) == 1);
  434. AZ_TEST_ASSERT(map.size() == 5);
  435. AZ_TEST_ASSERT(map.erase(10) == 0);
  436. AZ_TEST_ASSERT(map.size() == 5);
  437. AZ_TEST_ASSERT(map.erase(100) == 0);
  438. AZ_TEST_ASSERT(map.size() == 5);
  439. AZ_TEST_ASSERT(map.erase(20) == 2);
  440. AZ_TEST_ASSERT(map.size() == 3);
  441. //erase_one
  442. AZ_TEST_ASSERT(map.erase_one(30));
  443. AZ_TEST_ASSERT(map.size() == 2);
  444. AZ_TEST_ASSERT(map.erase(30) == 2);
  445. AZ_TEST_ASSERT(map.size() == 0);
  446. AZ_TEST_ASSERT(map.empty());
  447. //clear
  448. map.insert(10);
  449. AZ_TEST_ASSERT(!map.empty());
  450. map.clear();
  451. AZ_TEST_ASSERT(map.empty());
  452. AZ_TEST_ASSERT(map.erase(10) == 0);
  453. //assignment
  454. map.insert(10);
  455. map.insert(20);
  456. map.insert(30);
  457. Map map2(map);
  458. AZ_TEST_ASSERT(map2.size() == 3);
  459. AZ_TEST_ASSERT(map2.find(20));
  460. Map map3;
  461. map3 = map;
  462. AZ_TEST_ASSERT(map3.size() == 3);
  463. AZ_TEST_ASSERT(map3.find(20));
  464. map.erase(10);
  465. AZ_TEST_ASSERT(map.size() == 2);
  466. map.swap(map3);
  467. AZ_TEST_ASSERT(map.size() == 3);
  468. AZ_TEST_ASSERT(map3.size() == 2);
  469. {
  470. m_failures = 0;
  471. AZStd::thread thread0(AZStd::bind(&ConcurrentUnorderedMultiMapTestBase::InsertErase, this));
  472. AZStd::thread thread1(AZStd::bind(&ConcurrentUnorderedMultiMapTestBase::InsertErase, this));
  473. AZStd::thread thread2(AZStd::bind(&ConcurrentUnorderedMultiMapTestBase::InsertErase, this));
  474. AZStd::thread thread3(AZStd::bind(&ConcurrentUnorderedMultiMapTestBase::InsertErase, this));
  475. thread0.join();
  476. thread1.join();
  477. thread2.join();
  478. thread3.join();
  479. AZ_TEST_ASSERT(m_failures == 0);
  480. AZ_TEST_ASSERT(m_map.empty());
  481. }
  482. Map dummy;
  483. m_map.swap(dummy); // clear memory
  484. }
  485. private:
  486. #ifdef _DEBUG
  487. static const int NUM_ITERATIONS = 1;
  488. #else
  489. static const int NUM_ITERATIONS = 200;
  490. #endif
  491. static const int NUM_VALUES = 500;
  492. void InsertErase()
  493. {
  494. for (int iter = 0; iter < NUM_ITERATIONS; ++iter)
  495. {
  496. //insert
  497. for (int i = 0; i < NUM_VALUES; ++i)
  498. {
  499. if (!m_map.insert(AZStd::make_pair(i, i + 1)))
  500. {
  501. ++m_failures;
  502. }
  503. }
  504. //find
  505. for (int i = 0; i < NUM_VALUES; ++i)
  506. {
  507. int result = 0;
  508. if (!m_map.find(i, &result))
  509. {
  510. ++m_failures;
  511. }
  512. if (result != i + 1)
  513. {
  514. ++m_failures;
  515. }
  516. }
  517. //erase
  518. for (int i = 0; i < NUM_VALUES; ++i)
  519. {
  520. if (!m_map.erase_one(i))
  521. {
  522. ++m_failures;
  523. }
  524. }
  525. }
  526. }
  527. Map m_map;
  528. atomic<int> m_failures;
  529. };
  530. typedef ConcurrentUnorderedMultiMapTestBase<concurrent_unordered_multimap<int, int> > ConcurrentUnorderedMultiMapTest;
  531. typedef ConcurrentUnorderedMultiMapTestBase<concurrent_fixed_unordered_multimap<int, int, 1543, 2100> > ConcurrentFixedUnorderedMultiMapTest;
  532. TEST_F(ConcurrentUnorderedMultiMapTest, Test)
  533. {
  534. run();
  535. }
  536. TEST_F(ConcurrentFixedUnorderedMultiMapTest, Test)
  537. {
  538. run();
  539. }
  540. class ConcurrentVectorTest
  541. : public LeakDetectionFixture
  542. {
  543. public:
  544. void run()
  545. {
  546. //
  547. //single threaded functionality tests
  548. //
  549. concurrent_vector<int> testVector;
  550. AZ_TEST_ASSERT(testVector.empty());
  551. AZ_TEST_ASSERT(testVector.size() == 0);
  552. testVector.push_back(10);
  553. AZ_TEST_ASSERT(!testVector.empty());
  554. AZ_TEST_ASSERT(testVector.size() == 1);
  555. AZ_TEST_ASSERT(testVector[0] == 10);
  556. testVector[0] = 20;
  557. AZ_TEST_ASSERT(testVector[0] == 20);
  558. testVector.clear();
  559. AZ_TEST_ASSERT(testVector.empty());
  560. AZ_TEST_ASSERT(testVector.size() == 0);
  561. for (int i = 0; i < 100; ++i)
  562. {
  563. testVector.push_back(i + 1000);
  564. }
  565. AZ_TEST_ASSERT(testVector.size() == 100);
  566. for (int i = 0; i < 100; ++i)
  567. {
  568. AZ_TEST_ASSERT(testVector[i] == i + 1000);
  569. }
  570. //
  571. //multithread tests
  572. //
  573. {
  574. AZStd::thread thread0(AZStd::bind(&ConcurrentVectorTest::Push, this, 0));
  575. AZStd::thread thread1(AZStd::bind(&ConcurrentVectorTest::Push, this, 1));
  576. AZStd::thread thread2(AZStd::bind(&ConcurrentVectorTest::Push, this, 2));
  577. AZStd::thread thread3(AZStd::bind(&ConcurrentVectorTest::Push, this, 3));
  578. thread0.join();
  579. thread1.join();
  580. thread2.join();
  581. thread3.join();
  582. //verify vector contains the right values in the expected order
  583. AZ_TEST_ASSERT(m_vector.size() == 4 * NUM_ITERATIONS);
  584. int nextValue[4];
  585. for (int i = 0; i < 4; ++i)
  586. {
  587. nextValue[i] = i * NUM_ITERATIONS;
  588. }
  589. for (unsigned int vecIndex = 0; vecIndex < m_vector.size(); ++vecIndex)
  590. {
  591. int value = m_vector[vecIndex];
  592. bool isFound = false;
  593. for (int i = 0; i < 4; ++i)
  594. {
  595. if (nextValue[i] == value)
  596. {
  597. isFound = true;
  598. ++nextValue[i];
  599. break;
  600. }
  601. }
  602. AZ_TEST_ASSERT(isFound);
  603. }
  604. }
  605. }
  606. private:
  607. #if defined(_DEBUG)
  608. static const int NUM_ITERATIONS = 10000;
  609. #else
  610. static const int NUM_ITERATIONS = 500000;
  611. #endif
  612. void Push(int threadIndex)
  613. {
  614. for (int i = 0; i < NUM_ITERATIONS; ++i)
  615. {
  616. m_vector.push_back(threadIndex * NUM_ITERATIONS + i);
  617. }
  618. }
  619. concurrent_vector<int> m_vector;
  620. };
  621. TEST_F(ConcurrentVectorTest, Test)
  622. {
  623. run();
  624. }
  625. }