TestThreadStorage.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. #include "TestThread.h"
  5. #include <EATest/EATest.h>
  6. #include <eathread/eathread.h>
  7. #include <eathread/eathread_storage.h>
  8. #include <eathread/eathread_thread.h>
  9. using namespace EA::Thread;
  10. const int kMaxConcurrentThreadCount = EATHREAD_MAX_CONCURRENT_THREAD_COUNT;
  11. ///////////////////////////////////////////////////////////////////////////////
  12. // EA_THREAD_LOCAL tests
  13. //
  14. #ifdef EA_THREAD_LOCAL
  15. // Test declaration of basic int.
  16. EA_THREAD_LOCAL int gTLI = 0;
  17. // Test declaration of static int.
  18. static EA_THREAD_LOCAL int sTLI = 0;
  19. // Test declaration of struct.
  20. struct ThreadLocalData
  21. {
  22. int x;
  23. };
  24. EA_THREAD_LOCAL ThreadLocalData gTDL;
  25. #endif
  26. struct TLSWorkData
  27. {
  28. AtomicInt32 mShouldBegin;
  29. AtomicInt32 mShouldEnd;
  30. AtomicInt32 mnErrorCount;
  31. ThreadLocalStorage* mpTLS;
  32. TLSWorkData()
  33. : mShouldBegin(0), mShouldEnd(0), mnErrorCount(0), mpTLS(NULL) {}
  34. // define copy ctor and assignment operator
  35. // so the compiler does define them intrisically
  36. TLSWorkData(const TLSWorkData& rhs); // copy constructor
  37. TLSWorkData& operator=(const TLSWorkData& rhs); // assignment operator
  38. };
  39. static intptr_t TLSTestThreadFunction(void* pvWorkData)
  40. {
  41. TLSWorkData* pWorkData = (TLSWorkData*)pvWorkData;
  42. void* pValue;
  43. bool bResult;
  44. size_t i = 1;
  45. int nErrorCount = 0;
  46. while(pWorkData->mShouldBegin.GetValue() == 0) // Spin until we get the should-begin signal. We could also use a Semaphore for this, but our use here is very simple and not performance-oriented.
  47. EA::Thread::ThreadSleep(100);
  48. pValue = pWorkData->mpTLS->GetValue();
  49. EATEST_VERIFY_MSG(pValue == NULL, "ThreadLocalStorage failure.");
  50. do{
  51. bResult = pWorkData->mpTLS->SetValue((void*)i);
  52. EATEST_VERIFY_MSG(bResult, "ThreadLocalStorage failure.");
  53. pValue = pWorkData->mpTLS->GetValue();
  54. EATEST_VERIFY_MSG(pValue == (void*)i, "ThreadLocalStorage failure.");
  55. i++;
  56. ThreadCooperativeYield(); // Used by cooperative threading platforms.
  57. }while(pWorkData->mShouldEnd.GetValue() == 0);
  58. pValue = pWorkData->mpTLS->GetValue();
  59. EATEST_VERIFY_MSG(pValue != NULL, "ThreadLocalStorage failure.");
  60. pWorkData->mnErrorCount += nErrorCount;
  61. return 0;
  62. }
  63. static int TestThreadStorageSingle()
  64. {
  65. int nErrorCount(0);
  66. { // Re-use test
  67. void* pValue;
  68. ThreadLocalStorage tlsUnused;
  69. { // Give this its own scope.
  70. ThreadLocalStorage tls0;
  71. pValue = tls0.GetValue();
  72. EATEST_VERIFY_MSG(pValue == NULL, "ThreadLocalStorage failure.");
  73. tls0.SetValue((void*)1);
  74. }
  75. ThreadLocalStorage tls1;
  76. pValue = tls1.GetValue();
  77. EATEST_VERIFY_MSG(pValue == NULL, "ThreadLocalStorage failure.");
  78. }
  79. { // Single-threaded test
  80. #ifdef EA_THREAD_LOCAL
  81. // EA_THREAD_LOCAL tests
  82. gTLI = 1;
  83. sTLI = 1;
  84. gTDL.x = 1;
  85. if((gTLI + sTLI + gTDL.x) == 100000) // Prevent compiler warnings due to non-usage.
  86. EA::UnitTest::ReportVerbosity(1, "EA_THREAD_LOCAL: %d %d %d\n", gTLI, sTLI, gTDL.x);
  87. #endif
  88. // Test ThreadLocalStorage
  89. ThreadLocalStorage tlsA;
  90. ThreadLocalStorage tlsB;
  91. ThreadLocalStorage tlsC;
  92. void* pValue;
  93. void* pNULL = (void*)0;
  94. void* p1 = (void*)1;
  95. void* p2 = (void*)2;
  96. bool bResult;
  97. pValue = tlsA.GetValue();
  98. EATEST_VERIFY_MSG(pValue == pNULL, "ThreadLocalStorage failure.");
  99. pValue = tlsB.GetValue();
  100. EATEST_VERIFY_MSG(pValue == pNULL, "ThreadLocalStorage failure.");
  101. pValue = tlsC.GetValue();
  102. EATEST_VERIFY_MSG(pValue == pNULL, "ThreadLocalStorage failure.");
  103. bResult = tlsA.SetValue(pNULL);
  104. EATEST_VERIFY_MSG(bResult, "ThreadLocalStorage failure.");
  105. pValue = tlsA.GetValue();
  106. EATEST_VERIFY_MSG(pValue == pNULL, "ThreadLocalStorage failure.");
  107. bResult = tlsA.SetValue(p1);
  108. EATEST_VERIFY_MSG(bResult, "ThreadLocalStorage failure.");
  109. pValue = tlsA.GetValue();
  110. EATEST_VERIFY_MSG(pValue == p1, "ThreadLocalStorage failure.");
  111. bResult = tlsA.SetValue(pNULL);
  112. EATEST_VERIFY_MSG(bResult, "ThreadLocalStorage failure.");
  113. pValue = tlsA.GetValue();
  114. EATEST_VERIFY_MSG(pValue == pNULL, "ThreadLocalStorage failure.");
  115. bResult = tlsA.SetValue(p2);
  116. EATEST_VERIFY_MSG(bResult, "ThreadLocalStorage failure.");
  117. pValue = tlsA.GetValue();
  118. EATEST_VERIFY_MSG(pValue == p2, "ThreadLocalStorage failure.");
  119. }
  120. return nErrorCount;
  121. }
  122. static int TestThreadStorageMultiple()
  123. {
  124. int nErrorCount(0);
  125. const int kThreadCount(kMaxConcurrentThreadCount - 1);
  126. Thread thread[kThreadCount];
  127. ThreadId threadId[kThreadCount];
  128. Thread::Status status;
  129. int i;
  130. TLSWorkData workData;
  131. for(i = 0; i < kThreadCount; i++)
  132. {
  133. threadId[i] = thread[i].Begin(TLSTestThreadFunction, &workData);
  134. EATEST_VERIFY_MSG(threadId[i] != kThreadIdInvalid, "Thread failure: Couldn't create thread.");
  135. }
  136. workData.mpTLS = new ThreadLocalStorage;
  137. workData.mShouldBegin.SetValue(1);
  138. EA::UnitTest::ThreadSleepRandom(2000, 2000);
  139. workData.mShouldEnd.SetValue(1);
  140. EA::UnitTest::ThreadSleepRandom(1000, 1000);
  141. for(i = 0; i < kThreadCount; i++)
  142. {
  143. if(threadId[i] != kThreadIdInvalid)
  144. {
  145. status = thread[i].WaitForEnd(GetThreadTime() + 30000);
  146. EATEST_VERIFY_MSG(status == Thread::kStatusEnded, "Thread failure: Thread(s) didn't end.");
  147. }
  148. }
  149. delete workData.mpTLS;
  150. workData.mpTLS = NULL;
  151. nErrorCount += (int)workData.mnErrorCount;
  152. return nErrorCount;
  153. }
  154. int TestThreadStorage()
  155. {
  156. int nErrorCount(0);
  157. nErrorCount += TestThreadStorageSingle();
  158. #if EA_THREADS_AVAILABLE
  159. // Call this twice, to make sure recyling of TLS works properly.
  160. nErrorCount += TestThreadStorageMultiple();
  161. nErrorCount += TestThreadStorageMultiple();
  162. #endif
  163. return nErrorCount;
  164. }