atomic_ut.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #include "atomic.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <util/generic/ylimits.h>
  4. template <typename TAtomic>
  5. class TAtomicTest
  6. : public TTestBase {
  7. UNIT_TEST_SUITE(TAtomicTest);
  8. UNIT_TEST(TestAtomicInc1)
  9. UNIT_TEST(TestAtomicInc2)
  10. UNIT_TEST(TestAtomicGetAndInc)
  11. UNIT_TEST(TestAtomicDec)
  12. UNIT_TEST(TestAtomicGetAndDec)
  13. UNIT_TEST(TestAtomicAdd)
  14. UNIT_TEST(TestAtomicGetAndAdd)
  15. UNIT_TEST(TestAtomicSub)
  16. UNIT_TEST(TestAtomicGetAndSub)
  17. UNIT_TEST(TestAtomicSwap)
  18. UNIT_TEST(TestAtomicOr)
  19. UNIT_TEST(TestAtomicAnd)
  20. UNIT_TEST(TestAtomicXor)
  21. UNIT_TEST(TestCAS)
  22. UNIT_TEST(TestGetAndCAS)
  23. UNIT_TEST(TestLockUnlock)
  24. UNIT_TEST_SUITE_END();
  25. private:
  26. inline void TestLockUnlock() {
  27. TAtomic v = 0;
  28. UNIT_ASSERT(AtomicTryLock(&v));
  29. UNIT_ASSERT(!AtomicTryLock(&v));
  30. UNIT_ASSERT_VALUES_EQUAL(v, 1);
  31. AtomicUnlock(&v);
  32. UNIT_ASSERT_VALUES_EQUAL(v, 0);
  33. }
  34. inline void TestCAS() {
  35. TAtomic v = 0;
  36. UNIT_ASSERT(AtomicCas(&v, 1, 0));
  37. UNIT_ASSERT(!AtomicCas(&v, 1, 0));
  38. UNIT_ASSERT_VALUES_EQUAL(v, 1);
  39. UNIT_ASSERT(AtomicCas(&v, 0, 1));
  40. UNIT_ASSERT_VALUES_EQUAL(v, 0);
  41. UNIT_ASSERT(AtomicCas(&v, Max<intptr_t>(), 0));
  42. UNIT_ASSERT_VALUES_EQUAL(v, Max<intptr_t>());
  43. }
  44. inline void TestGetAndCAS() {
  45. TAtomic v = 0;
  46. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndCas(&v, 1, 0), 0);
  47. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndCas(&v, 2, 0), 1);
  48. UNIT_ASSERT_VALUES_EQUAL(v, 1);
  49. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndCas(&v, 0, 1), 1);
  50. UNIT_ASSERT_VALUES_EQUAL(v, 0);
  51. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndCas(&v, Max<intptr_t>(), 0), 0);
  52. UNIT_ASSERT_VALUES_EQUAL(v, Max<intptr_t>());
  53. }
  54. inline void TestAtomicInc1() {
  55. TAtomic v = 0;
  56. UNIT_ASSERT(AtomicAdd(v, 1));
  57. UNIT_ASSERT_VALUES_EQUAL(v, 1);
  58. UNIT_ASSERT(AtomicAdd(v, 10));
  59. UNIT_ASSERT_VALUES_EQUAL(v, 11);
  60. }
  61. inline void TestAtomicInc2() {
  62. TAtomic v = 0;
  63. UNIT_ASSERT(AtomicIncrement(v));
  64. UNIT_ASSERT_VALUES_EQUAL(v, 1);
  65. UNIT_ASSERT(AtomicIncrement(v));
  66. UNIT_ASSERT_VALUES_EQUAL(v, 2);
  67. }
  68. inline void TestAtomicGetAndInc() {
  69. TAtomic v = 0;
  70. UNIT_ASSERT_EQUAL(AtomicGetAndIncrement(v), 0);
  71. UNIT_ASSERT_VALUES_EQUAL(v, 1);
  72. UNIT_ASSERT_EQUAL(AtomicGetAndIncrement(v), 1);
  73. UNIT_ASSERT_VALUES_EQUAL(v, 2);
  74. }
  75. inline void TestAtomicDec() {
  76. TAtomic v = 2;
  77. UNIT_ASSERT(AtomicDecrement(v));
  78. UNIT_ASSERT_VALUES_EQUAL(v, 1);
  79. UNIT_ASSERT(!AtomicDecrement(v));
  80. UNIT_ASSERT_VALUES_EQUAL(v, 0);
  81. }
  82. inline void TestAtomicGetAndDec() {
  83. TAtomic v = 2;
  84. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndDecrement(v), 2);
  85. UNIT_ASSERT_VALUES_EQUAL(v, 1);
  86. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndDecrement(v), 1);
  87. UNIT_ASSERT_VALUES_EQUAL(v, 0);
  88. }
  89. inline void TestAtomicAdd() {
  90. TAtomic v = 0;
  91. UNIT_ASSERT_VALUES_EQUAL(AtomicAdd(v, 1), 1);
  92. UNIT_ASSERT_VALUES_EQUAL(AtomicAdd(v, 2), 3);
  93. UNIT_ASSERT_VALUES_EQUAL(AtomicAdd(v, -4), -1);
  94. UNIT_ASSERT_VALUES_EQUAL(v, -1);
  95. }
  96. inline void TestAtomicGetAndAdd() {
  97. TAtomic v = 0;
  98. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndAdd(v, 1), 0);
  99. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndAdd(v, 2), 1);
  100. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndAdd(v, -4), 3);
  101. UNIT_ASSERT_VALUES_EQUAL(v, -1);
  102. }
  103. inline void TestAtomicSub() {
  104. TAtomic v = 4;
  105. UNIT_ASSERT_VALUES_EQUAL(AtomicSub(v, 1), 3);
  106. UNIT_ASSERT_VALUES_EQUAL(AtomicSub(v, 2), 1);
  107. UNIT_ASSERT_VALUES_EQUAL(AtomicSub(v, 3), -2);
  108. UNIT_ASSERT_VALUES_EQUAL(v, -2);
  109. }
  110. inline void TestAtomicGetAndSub() {
  111. TAtomic v = 4;
  112. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndSub(v, 1), 4);
  113. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndSub(v, 2), 3);
  114. UNIT_ASSERT_VALUES_EQUAL(AtomicGetAndSub(v, 3), 1);
  115. UNIT_ASSERT_VALUES_EQUAL(v, -2);
  116. }
  117. inline void TestAtomicSwap() {
  118. TAtomic v = 0;
  119. UNIT_ASSERT_VALUES_EQUAL(AtomicSwap(&v, 3), 0);
  120. UNIT_ASSERT_VALUES_EQUAL(AtomicSwap(&v, 5), 3);
  121. UNIT_ASSERT_VALUES_EQUAL(AtomicSwap(&v, -7), 5);
  122. UNIT_ASSERT_VALUES_EQUAL(AtomicSwap(&v, Max<intptr_t>()), -7);
  123. UNIT_ASSERT_VALUES_EQUAL(v, Max<intptr_t>());
  124. }
  125. inline void TestAtomicOr() {
  126. TAtomic v = 0xf0;
  127. UNIT_ASSERT_VALUES_EQUAL(AtomicOr(v, 0x0f), 0xff);
  128. UNIT_ASSERT_VALUES_EQUAL(v, 0xff);
  129. }
  130. inline void TestAtomicAnd() {
  131. TAtomic v = 0xff;
  132. UNIT_ASSERT_VALUES_EQUAL(AtomicAnd(v, 0xf0), 0xf0);
  133. UNIT_ASSERT_VALUES_EQUAL(v, 0xf0);
  134. }
  135. inline void TestAtomicXor() {
  136. TAtomic v = 0x00;
  137. UNIT_ASSERT_VALUES_EQUAL(AtomicXor(v, 0xff), 0xff);
  138. UNIT_ASSERT_VALUES_EQUAL(AtomicXor(v, 0xff), 0x00);
  139. }
  140. inline void TestAtomicPtr() {
  141. int* p;
  142. AtomicSet(p, nullptr);
  143. UNIT_ASSERT_VALUES_EQUAL(AtomicGet(p), 0);
  144. int i;
  145. AtomicSet(p, &i);
  146. UNIT_ASSERT_VALUES_EQUAL(AtomicGet(p), &i);
  147. UNIT_ASSERT_VALUES_EQUAL(AtomicSwap(&p, nullptr), &i);
  148. UNIT_ASSERT(AtomicCas(&p, &i, nullptr));
  149. }
  150. };
  151. UNIT_TEST_SUITE_REGISTRATION(TAtomicTest<TAtomic>);
  152. #ifndef _MSC_VER
  153. // chooses type *other than* T1
  154. template <typename T1, typename T2, typename T3>
  155. struct TChooser {
  156. using TdType = T2;
  157. };
  158. template <typename T1, typename T2>
  159. struct TChooser<T1, T1, T2> {
  160. using TdType = T2;
  161. };
  162. template <typename T1>
  163. struct TChooser<T1, T1, T1> {};
  164. #if defined(__IOS__) && defined(_32_)
  165. using TAltAtomic = int;
  166. #else
  167. using TAltAtomic = volatile TChooser<TAtomicBase, long, long long>::TdType;
  168. #endif
  169. class TTTest: public TAtomicTest<TAltAtomic> {
  170. public:
  171. TString Name() const noexcept override {
  172. return "TAtomicTest<TAltAtomic>";
  173. }
  174. static TString StaticName() noexcept {
  175. return "TAtomicTest<TAltAtomic>";
  176. }
  177. };
  178. UNIT_TEST_SUITE_REGISTRATION(TTTest);
  179. #endif