TestThreadBarrier.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. #include "TestThread.h"
  5. #include <EATest/EATest.h>
  6. #include <eathread/eathread_thread.h>
  7. #include <eathread/eathread_mutex.h>
  8. #include <eathread/eathread_barrier.h>
  9. #include <stdlib.h>
  10. using namespace EA::Thread;
  11. const int kMaxConcurrentThreadCount = EATHREAD_MAX_CONCURRENT_THREAD_COUNT;
  12. struct BT_WorkData
  13. {
  14. Barrier* mpBarrier;
  15. int mnSleepTime;
  16. AtomicInt32 mnErrorCount;
  17. BT_WorkData(Barrier* pBarrier = NULL, int nSleepTime = 0)
  18. : mpBarrier(pBarrier), mnSleepTime(nSleepTime), mnErrorCount(0) {}
  19. };
  20. static intptr_t BT_ConsumerFunction(void* pvWorkData)
  21. {
  22. int nErrorCount = 0;
  23. BT_WorkData* pWorkData = (BT_WorkData*)pvWorkData;
  24. const ThreadId threadId = GetThreadId();
  25. EA::UnitTest::ReportVerbosity(1, "Barrier consumer test function created: %s\n", EAThreadThreadIdToString(threadId));
  26. // Here we would actually do the job, but printing 'job done' is enough in itself.
  27. ThreadSleep((ThreadTime)pWorkData->mnSleepTime);
  28. EA::UnitTest::ReportVerbosity(1, "Job done by thread %s.\n", EAThreadThreadIdToString(threadId));
  29. EA::UnitTest::ReportVerbosity(1, "Start synchronizing by thread %s.\n", EAThreadThreadIdToString(threadId));
  30. const Barrier::Result result = pWorkData->mpBarrier->Wait(GetThreadTime() + 10000);
  31. if(result == Barrier::kResultPrimary)
  32. {
  33. // This is the first thread to be released: call producer function
  34. EA::UnitTest::ReportVerbosity(1, "Serial execution at Barrier by thread %s\n", EAThreadThreadIdToString(threadId));
  35. }
  36. else if(result == Barrier::kResultTimeout)
  37. {
  38. EA::UnitTest::Report("Barrier time-out by thread %s\n", EAThreadThreadIdToString(threadId));
  39. nErrorCount++;
  40. }
  41. else if(result == Barrier::kResultError)
  42. {
  43. EA::UnitTest::Report("Barrier error in thread %s\n", EAThreadThreadIdToString(threadId));
  44. nErrorCount++;
  45. }
  46. pWorkData->mnErrorCount += nErrorCount;
  47. ThreadSleep((ThreadTime)pWorkData->mnSleepTime);
  48. EA::UnitTest::ReportVerbosity(1, "Job synchronized by thread %s.\n", EAThreadThreadIdToString(threadId));
  49. return 0;
  50. }
  51. static intptr_t BT_ConsumerFunction2(void * pvWorkData)
  52. {
  53. ((Barrier*)pvWorkData)->Wait();
  54. ((Barrier*)pvWorkData)->Wait();
  55. return 0;
  56. }
  57. int TestThreadBarrier()
  58. {
  59. int nErrorCount(0);
  60. #if EA_THREADS_AVAILABLE
  61. {
  62. Thread::Status status;
  63. const int kThreadCount(kMaxConcurrentThreadCount - 1);
  64. BT_WorkData workData[kThreadCount];
  65. Thread threads[kThreadCount];
  66. ThreadId threadId[kThreadCount];
  67. Barrier barrier(kThreadCount);
  68. int i;
  69. for(i = 0; i < kThreadCount; i++)
  70. {
  71. workData[i].mpBarrier = &barrier;
  72. workData[i].mnSleepTime = (i + 1) * 500;
  73. }
  74. for(i = 0; i < kThreadCount; i++)
  75. {
  76. threadId[i] = threads[i].Begin(BT_ConsumerFunction, &workData[i]);
  77. EATEST_VERIFY_MSG(threadId[i] != kThreadIdInvalid, "Barrier/Thread failure: Couldn't create thread.");
  78. }
  79. EA::UnitTest::ThreadSleepRandom(2000, 2000);
  80. for(i = 0; i < kThreadCount; i++)
  81. {
  82. if(threadId[i] != kThreadIdInvalid)
  83. {
  84. status = threads[i].WaitForEnd(GetThreadTime() + 30000);
  85. EATEST_VERIFY_MSG(status != Thread::kStatusRunning, "Barrier/Thread failure.");
  86. }
  87. nErrorCount += workData[i].mnErrorCount;
  88. }
  89. }
  90. {
  91. Thread threads[2];
  92. ThreadId threadId[2];
  93. Barrier barrier(2);
  94. Thread::Status status;
  95. threadId[0] = threads[0].Begin(BT_ConsumerFunction2, &barrier);
  96. EATEST_VERIFY_MSG(threadId[0] != kThreadIdInvalid, "Barrier/Thread failure: Couldn't create thread.");
  97. threadId[1] = threads[1].Begin(BT_ConsumerFunction2, &barrier);
  98. EATEST_VERIFY_MSG(threadId[1] != kThreadIdInvalid, "Barrier/Thread failure: Couldn't create thread.");
  99. if(threadId[0] != kThreadIdInvalid)
  100. {
  101. status = threads[0].WaitForEnd();
  102. EATEST_VERIFY_MSG(status != Thread::kStatusRunning, "Barrier/Thread failure.");
  103. }
  104. if(threadId[1] != kThreadIdInvalid)
  105. {
  106. status = threads[1].WaitForEnd();
  107. EATEST_VERIFY_MSG(status != Thread::kStatusRunning, "Barrier/Thread failure.");
  108. }
  109. }
  110. #endif
  111. return nErrorCount;
  112. }