Thread.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright (C) 2014, 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. ANKI_TEST(Util, Thread)
  13. {
  14. static const char* THREAD_NAME = "name";
  15. Thread t(THREAD_NAME);
  16. static const U64 NUMBER = 0xFAFAFAFABABABA;
  17. U64 u = NUMBER;
  18. t.start(&u, [](Thread::Info& info) -> Error
  19. {
  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. {
  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. {
  65. In& in = *reinterpret_cast<In*>(info.m_userData);
  66. I64& num = in.m_num;
  67. Mutex& mtx = *in.m_mtx;
  68. for(U i = 0; i < ITERATIONS; i++)
  69. {
  70. mtx.lock();
  71. --num;
  72. mtx.unlock();
  73. }
  74. return ErrorCode::NONE;
  75. });
  76. ANKI_TEST_EXPECT_NO_ERR(t0.join());
  77. ANKI_TEST_EXPECT_NO_ERR(t1.join());
  78. ANKI_TEST_EXPECT_EQ(in.m_num, ITERATIONS * 2);
  79. }
  80. //==============================================================================
  81. /// Struct for our tests
  82. struct TestJobTP: Threadpool::Task
  83. {
  84. U32 in = 0;
  85. U32 iterations = 0;
  86. Error operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
  87. {
  88. for(U32 i = 0; i < iterations; i++)
  89. {
  90. ++in;
  91. }
  92. return ErrorCode::NONE;
  93. }
  94. };
  95. } // end namespace anki
  96. ANKI_TEST(Util, Threadpool)
  97. {
  98. const U32 threadsCount = 4;
  99. const U32 repeat = 5;
  100. Threadpool* tp = new Threadpool(threadsCount);
  101. TestJobTP jobs[threadsCount];
  102. for(U32 i = 1; i < repeat; i++)
  103. {
  104. U32 iterations = rand() % 100000;
  105. for(U32 j = 0; j < threadsCount; j++)
  106. {
  107. jobs[j].in = i;
  108. jobs[j].iterations = iterations;
  109. tp->assignNewTask(j, &jobs[j]);
  110. }
  111. ANKI_TEST_EXPECT_NO_ERR(tp->waitForAllThreadsToFinish());
  112. for(U32 j = 0; j < threadsCount; j++)
  113. {
  114. ANKI_TEST_EXPECT_EQ(jobs[j].in, i + iterations);
  115. }
  116. }
  117. delete tp;
  118. }
  119. //==============================================================================
  120. ANKI_TEST(Util, Barrier)
  121. {
  122. // Simple test
  123. {
  124. Barrier b(2);
  125. Thread t(nullptr);
  126. t.start(&b, [](Thread::Info& info) -> Error
  127. {
  128. Barrier& b = *reinterpret_cast<Barrier*>(info.m_userData);
  129. b.wait();
  130. return ErrorCode::NONE;
  131. });
  132. b.wait();
  133. ANKI_TEST_EXPECT_NO_ERR(t.join());
  134. }
  135. }