ThreadTests.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include <threads.h>
  2. #include "../Tests.hpp"
  3. #include "core/thread/Mutex.hpp"
  4. #include "core/thread/SpinLock.hpp"
  5. #include "core/thread/Thread.hpp"
  6. #include "core/utils/Clock.hpp"
  7. static int runDone = 0;
  8. struct IntHolder {
  9. int value;
  10. };
  11. static int run(void*) {
  12. runDone = 1;
  13. return 7;
  14. }
  15. static void testStart() {
  16. runDone = 0;
  17. Core::Thread t;
  18. CORE_TEST_FALSE(t.start(run, nullptr));
  19. int returnValue = 0;
  20. CORE_TEST_FALSE(t.join(&returnValue));
  21. CORE_TEST_EQUAL(1, runDone);
  22. CORE_TEST_EQUAL(7, returnValue);
  23. }
  24. static void testLambda() {
  25. IntHolder i(0);
  26. Core::Thread t;
  27. CORE_TEST_FALSE(t.start(
  28. [](void* p) {
  29. IntHolder* ip = static_cast<IntHolder*>(p);
  30. ip->value = 2;
  31. return 0;
  32. },
  33. &i));
  34. CORE_TEST_FALSE(t.join(nullptr));
  35. CORE_TEST_EQUAL(2, i.value);
  36. }
  37. static void testJoinWithoutStart() {
  38. Core::Thread t;
  39. CORE_TEST_TRUE(t.join(nullptr));
  40. }
  41. static void testAutoJoin() {
  42. Core::Thread t;
  43. CORE_TEST_FALSE(t.start([](void*) { return 0; }, nullptr));
  44. }
  45. static void testMove() {
  46. Core::Thread t;
  47. CORE_TEST_FALSE(t.start([](void*) { return 0; }, nullptr));
  48. Core::Thread m = Core::move(t);
  49. CORE_TEST_FALSE(m.join());
  50. }
  51. static void testMoveAssignment() {
  52. Core::Thread t;
  53. CORE_TEST_FALSE(t.start([](void*) { return 0; }, nullptr));
  54. Core::Thread m;
  55. m = Core::move(t);
  56. CORE_TEST_FALSE(m.join());
  57. }
  58. static void testMoveIntoActive() {
  59. Core::Thread t;
  60. CORE_TEST_FALSE(t.start([](void*) { return 0; }, nullptr));
  61. Core::Thread m;
  62. t = Core::move(m);
  63. }
  64. static void testDoubleJoin() {
  65. Core::Thread t;
  66. CORE_TEST_FALSE(t.start([](void*) { return 0; }, nullptr));
  67. CORE_TEST_FALSE(t.join(nullptr));
  68. CORE_TEST_TRUE(t.join(nullptr));
  69. }
  70. struct MutexCounter {
  71. Core::Mutex m{};
  72. int counter = 0;
  73. };
  74. static int incrementMutexCounter(void* p) {
  75. MutexCounter* mcp = static_cast<MutexCounter*>(p);
  76. for(int i = 0; i < 10000; i++) {
  77. (void)mcp->m.lock();
  78. mcp->counter++;
  79. (void)mcp->m.unlock();
  80. }
  81. return 0;
  82. }
  83. static void testMutex() {
  84. Core::Clock::Nanos n;
  85. CORE_TEST_ERROR(Core::Clock::getNanos(n));
  86. MutexCounter mc;
  87. CORE_TEST_FALSE(mc.m.init());
  88. Core::Thread t[2];
  89. CORE_TEST_FALSE(t[0].start(incrementMutexCounter, &mc));
  90. CORE_TEST_FALSE(t[1].start(incrementMutexCounter, &mc));
  91. CORE_TEST_FALSE(t[0].join(nullptr));
  92. CORE_TEST_FALSE(t[1].join(nullptr));
  93. CORE_TEST_EQUAL(20000, mc.counter);
  94. Core::Clock::Nanos n2;
  95. CORE_TEST_ERROR(Core::Clock::getNanos(n2));
  96. Core::ArrayString<64> s;
  97. s.append(n2 - n).append("ns Mutex").printLine();
  98. }
  99. struct SpinLockCounter {
  100. Core::SpinLock s{};
  101. int counter = 0;
  102. };
  103. static int incrementSpinLockCounter(void* p) {
  104. SpinLockCounter* mcp = static_cast<SpinLockCounter*>(p);
  105. for(int i = 0; i < 10000; i++) {
  106. mcp->s.lock();
  107. mcp->counter++;
  108. mcp->s.unlock();
  109. }
  110. return 0;
  111. }
  112. static void testSpinLock() {
  113. Core::Clock::Nanos n;
  114. CORE_TEST_ERROR(Core::Clock::getNanos(n));
  115. SpinLockCounter sc;
  116. Core::Thread t[2];
  117. CORE_TEST_FALSE(t[0].start(incrementSpinLockCounter, &sc));
  118. CORE_TEST_FALSE(t[1].start(incrementSpinLockCounter, &sc));
  119. CORE_TEST_FALSE(t[0].join(nullptr));
  120. CORE_TEST_FALSE(t[1].join(nullptr));
  121. CORE_TEST_EQUAL(20000, sc.counter);
  122. Core::Clock::Nanos n2;
  123. CORE_TEST_ERROR(Core::Clock::getNanos(n2));
  124. Core::ArrayString<64> s;
  125. s.append(n2 - n).append("ns SpinLock").printLine();
  126. }
  127. static void testDoubleStart() {
  128. Core::Thread t;
  129. CORE_TEST_FALSE(t.start([](void*) { return 0; }, nullptr));
  130. CORE_TEST_TRUE(t.start([](void*) { return 0; }, nullptr));
  131. }
  132. void Core::testThread() {
  133. testStart();
  134. testLambda();
  135. testJoinWithoutStart();
  136. testAutoJoin();
  137. testMove();
  138. testMoveAssignment();
  139. testMoveIntoActive();
  140. testDoubleJoin();
  141. testMutex();
  142. testSpinLock();
  143. testDoubleStart();
  144. }