Thread.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
  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 <cstring>
  10. namespace anki
  11. {
  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, [](Thread::Info& 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. //==============================================================================
  37. ANKI_TEST(Util, Mutex)
  38. {
  39. Thread t0(nullptr), t1(nullptr);
  40. Mutex mtx;
  41. static const U ITERATIONS = 1000000;
  42. class In
  43. {
  44. public:
  45. I64 m_num = ITERATIONS;
  46. Mutex* m_mtx;
  47. };
  48. In in;
  49. in.m_mtx = &mtx;
  50. t0.start(&in, [](Thread::Info& info) -> Error {
  51. In& in = *reinterpret_cast<In*>(info.m_userData);
  52. I64& num = in.m_num;
  53. Mutex& mtx = *in.m_mtx;
  54. for(U i = 0; i < ITERATIONS; i++)
  55. {
  56. mtx.lock();
  57. num += 2;
  58. mtx.unlock();
  59. }
  60. return ErrorCode::NONE;
  61. });
  62. t1.start(&in, [](Thread::Info& info) -> Error {
  63. In& in = *reinterpret_cast<In*>(info.m_userData);
  64. I64& num = in.m_num;
  65. Mutex& mtx = *in.m_mtx;
  66. for(U i = 0; i < ITERATIONS; i++)
  67. {
  68. mtx.lock();
  69. --num;
  70. mtx.unlock();
  71. }
  72. return ErrorCode::NONE;
  73. });
  74. ANKI_TEST_EXPECT_NO_ERR(t0.join());
  75. ANKI_TEST_EXPECT_NO_ERR(t1.join());
  76. ANKI_TEST_EXPECT_EQ(in.m_num, ITERATIONS * 2);
  77. }
  78. //==============================================================================
  79. /// Struct for our tests
  80. struct TestJobTP : ThreadPool::Task
  81. {
  82. U32 in = 0;
  83. U32 iterations = 0;
  84. Error operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
  85. {
  86. for(U32 i = 0; i < iterations; i++)
  87. {
  88. ++in;
  89. }
  90. return ErrorCode::NONE;
  91. }
  92. };
  93. } // end namespace anki
  94. ANKI_TEST(Util, ThreadPool)
  95. {
  96. const U32 threadsCount = 4;
  97. const U32 repeat = 5;
  98. ThreadPool* tp = new ThreadPool(threadsCount);
  99. TestJobTP jobs[threadsCount];
  100. for(U32 i = 1; i < repeat; i++)
  101. {
  102. U32 iterations = rand() % 100000;
  103. for(U32 j = 0; j < threadsCount; j++)
  104. {
  105. jobs[j].in = i;
  106. jobs[j].iterations = iterations;
  107. tp->assignNewTask(j, &jobs[j]);
  108. }
  109. ANKI_TEST_EXPECT_NO_ERR(tp->waitForAllThreadsToFinish());
  110. for(U32 j = 0; j < threadsCount; j++)
  111. {
  112. ANKI_TEST_EXPECT_EQ(jobs[j].in, i + iterations);
  113. }
  114. }
  115. delete tp;
  116. }
  117. //==============================================================================
  118. ANKI_TEST(Util, Barrier)
  119. {
  120. // Simple test
  121. {
  122. Barrier b(2);
  123. Thread t(nullptr);
  124. t.start(&b, [](Thread::Info& info) -> Error {
  125. Barrier& b = *reinterpret_cast<Barrier*>(info.m_userData);
  126. b.wait();
  127. return ErrorCode::NONE;
  128. });
  129. b.wait();
  130. ANKI_TEST_EXPECT_NO_ERR(t.join());
  131. }
  132. }