Thread.cpp 3.4 KB

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