Thread.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include "tests/framework/Framework.h"
  6. #include "anki/util/Thread.h"
  7. #include "anki/util/StdTypes.h"
  8. #include "anki/util/HighRezTimer.h"
  9. #include "anki/util/ThreadPool.h"
  10. #include <cstring>
  11. namespace anki
  12. {
  13. ANKI_TEST(Util, Thread)
  14. {
  15. static const char* THREAD_NAME = "name";
  16. Thread t(THREAD_NAME);
  17. static const U64 NUMBER = 0xFAFAFAFABABABA;
  18. U64 u = NUMBER;
  19. t.start(&u, [](ThreadCallbackInfo& info) -> Error {
  20. Bool check = true;
  21. // Check name
  22. check = check && (std::strcmp(info.m_threadName, THREAD_NAME) == 0);
  23. // Check user value
  24. U64& num = *reinterpret_cast<U64*>(info.m_userData);
  25. check = check && (num == NUMBER);
  26. // Change number
  27. num = 0xF00;
  28. HighRezTimer::sleep(1.0);
  29. return (check != true) ? ErrorCode::FUNCTION_FAILED : ErrorCode::NONE;
  30. });
  31. ANKI_TEST_EXPECT_EQ(u, NUMBER); // It should be the old value
  32. Error err = t.join();
  33. ANKI_TEST_EXPECT_EQ(err, 0);
  34. ANKI_TEST_EXPECT_EQ(u, 0xF00);
  35. }
  36. ANKI_TEST(Util, Mutex)
  37. {
  38. Thread t0(nullptr), t1(nullptr);
  39. Mutex mtx;
  40. static const U ITERATIONS = 1000000;
  41. class In
  42. {
  43. public:
  44. I64 m_num = ITERATIONS;
  45. Mutex* m_mtx;
  46. };
  47. In in;
  48. in.m_mtx = &mtx;
  49. t0.start(&in, [](ThreadCallbackInfo& info) -> Error {
  50. In& in = *reinterpret_cast<In*>(info.m_userData);
  51. I64& num = in.m_num;
  52. Mutex& mtx = *in.m_mtx;
  53. for(U i = 0; i < ITERATIONS; i++)
  54. {
  55. mtx.lock();
  56. num += 2;
  57. mtx.unlock();
  58. }
  59. return ErrorCode::NONE;
  60. });
  61. t1.start(&in, [](ThreadCallbackInfo& info) -> Error {
  62. In& in = *reinterpret_cast<In*>(info.m_userData);
  63. I64& num = in.m_num;
  64. Mutex& mtx = *in.m_mtx;
  65. for(U i = 0; i < ITERATIONS; i++)
  66. {
  67. mtx.lock();
  68. --num;
  69. mtx.unlock();
  70. }
  71. return ErrorCode::NONE;
  72. });
  73. ANKI_TEST_EXPECT_NO_ERR(t0.join());
  74. ANKI_TEST_EXPECT_NO_ERR(t1.join());
  75. ANKI_TEST_EXPECT_EQ(in.m_num, ITERATIONS * 2);
  76. }
  77. /// Struct for our tests
  78. struct TestJobTP : ThreadPoolTask
  79. {
  80. U32 in = 0;
  81. U32 iterations = 0;
  82. Error operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
  83. {
  84. for(U32 i = 0; i < iterations; i++)
  85. {
  86. ++in;
  87. }
  88. return ErrorCode::NONE;
  89. }
  90. };
  91. } // end namespace anki
  92. ANKI_TEST(Util, ThreadPool)
  93. {
  94. const U32 threadsCount = 4;
  95. const U32 repeat = 5;
  96. ThreadPool* tp = new ThreadPool(threadsCount);
  97. TestJobTP jobs[threadsCount];
  98. for(U32 i = 1; i < repeat; i++)
  99. {
  100. U32 iterations = rand() % 100000;
  101. for(U32 j = 0; j < threadsCount; j++)
  102. {
  103. jobs[j].in = i;
  104. jobs[j].iterations = iterations;
  105. tp->assignNewTask(j, &jobs[j]);
  106. }
  107. ANKI_TEST_EXPECT_NO_ERR(tp->waitForAllThreadsToFinish());
  108. for(U32 j = 0; j < threadsCount; j++)
  109. {
  110. ANKI_TEST_EXPECT_EQ(jobs[j].in, i + iterations);
  111. }
  112. }
  113. delete tp;
  114. }
  115. ANKI_TEST(Util, Barrier)
  116. {
  117. // Simple test
  118. {
  119. Barrier b(2);
  120. Thread t(nullptr);
  121. t.start(&b, [](ThreadCallbackInfo& info) -> Error {
  122. Barrier& b = *reinterpret_cast<Barrier*>(info.m_userData);
  123. b.wait();
  124. return ErrorCode::NONE;
  125. });
  126. b.wait();
  127. ANKI_TEST_EXPECT_NO_ERR(t.join());
  128. }
  129. }