Thread.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. #include "BeefySysLib/Common.h"
  2. #include "BfObjects.h"
  3. #include "Thread.h"
  4. //#include "ThreadLocalStorage.h"
  5. #include "StompAlloc.h"
  6. //#include <crtdbg.h>
  7. //#define USE_STOMP_ALLOC
  8. #undef MemoryBarrier
  9. using namespace bf::System;
  10. using namespace bf::System::Threading;
  11. #ifdef BF_THREAD_TLS
  12. BF_TLS_DECLSPEC Thread* Thread::sCurrentThread;
  13. #endif
  14. static volatile int gLiveThreadCount;
  15. static Beefy::SyncEvent gThreadsDoneEvent;
  16. bf::System::Threading::Thread* BfGetCurrentThread()
  17. {
  18. #ifdef BF_THREAD_TLS
  19. return Thread::sCurrentThread;
  20. #else
  21. Thread* internalThread = (Thread*)BfpTLS_GetValue(BfTLSManager::sInternalThreadKey);
  22. return internalThread;
  23. #endif
  24. }
  25. void Thread::SuspendInternal()
  26. {
  27. BfpThread_Suspend(GetInternalThread()->mThreadHandle, NULL);
  28. }
  29. void Thread::ResumeInternal()
  30. {
  31. BfpThread_Resume(GetInternalThread()->mThreadHandle, NULL);
  32. }
  33. void Thread::InterruptInternal()
  34. {
  35. //TODO:
  36. }
  37. void Thread::SetJoinOnDelete(bool joinOnDelete)
  38. {
  39. auto internalThread = GetInternalThread();
  40. Beefy::AutoCrit autoCrit(internalThread->mCritSect);
  41. internalThread->mJoinOnDelete = joinOnDelete;
  42. }
  43. int Thread::GetPriorityNative()
  44. {
  45. return (int)BfpThread_GetPriority(GetInternalThread()->mThreadHandle, NULL) + 2;
  46. }
  47. void Thread::SetPriorityNative(int priority)
  48. {
  49. return BfpThread_SetPriority(GetInternalThread()->mThreadHandle, (BfpThreadPriority)(priority - 2), NULL);
  50. }
  51. bool Thread::GetIsAlive()
  52. {
  53. if (GetInternalThread() == NULL)
  54. return false;
  55. bool success = BfpThread_WaitFor(GetInternalThread()->mThreadHandle, 0);
  56. return !success;
  57. }
  58. bool Thread::GetIsThreadPoolThread()
  59. {
  60. return false;
  61. }
  62. bool Thread::JoinInternal(int millisecondsTimeout)
  63. {
  64. auto internalThread = GetInternalThread();
  65. if (internalThread == NULL)
  66. return true;
  67. bool success = BfpThread_WaitFor(internalThread->mThreadHandle, millisecondsTimeout);
  68. return success;
  69. }
  70. void Thread::SleepInternal(int millisecondsTimeout)
  71. {
  72. BfpThread_Sleep(millisecondsTimeout);
  73. }
  74. void Thread::SpinWaitInternal(int iterations)
  75. {
  76. BF_COMPILER_FENCE();
  77. BF_SPINWAIT_NOP();
  78. }
  79. bool Thread::YieldInternal()
  80. {
  81. return BfpThread_Yield();
  82. }
  83. Thread* Thread::GetCurrentThreadNative()
  84. {
  85. return BfGetCurrentThread();
  86. }
  87. unsigned long Thread::GetProcessDefaultStackSize()
  88. {
  89. return 0;
  90. }
  91. static void BF_CALLTYPE CStartProc(void* threadParam)
  92. {
  93. Thread* thread = (Thread*)threadParam;
  94. #ifdef BF_THREAD_TLS
  95. Thread::sCurrentThread = thread;
  96. #else
  97. BfpTLS_SetValue(BfTLSManager::sInternalThreadKey, thread);
  98. #endif
  99. auto internalThread = thread->GetInternalThread();
  100. // Hold lock until we get ThreadStarted callback
  101. internalThread->mCritSect.Lock();
  102. internalThread->mStartedEvent.Set(true);
  103. internalThread->mThreadHandle = BfpThread_GetCurrent();
  104. internalThread->mStackStart = (intptr)&thread;
  105. internalThread->ThreadStarted();
  106. bool isAutoDelete = gBfRtCallbacks.Thread_IsAutoDelete(thread);
  107. gBfRtCallbacks.Thread_ThreadProc(thread);
  108. bool isLastThread = BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, -1) == 1;
  109. //printf("Stopping thread\n");
  110. bool wantsDelete = false;
  111. //
  112. {
  113. internalThread->ThreadStopped();
  114. Beefy::AutoCrit autoCrit(internalThread->mCritSect);
  115. if (isAutoDelete)
  116. gBfRtCallbacks.Thread_AutoDelete(thread);
  117. internalThread->mDone = true;
  118. if (internalThread->mThread == NULL)
  119. {
  120. // If the thread was already deleted then we need to delete ourselves now
  121. wantsDelete = true;
  122. }
  123. }
  124. if (wantsDelete)
  125. delete internalThread;
  126. if (isLastThread)
  127. gThreadsDoneEvent.Set(false);
  128. //printf("Thread stopped\n");
  129. }
  130. void BfInternalThread::WaitForAllDone()
  131. {
  132. if ((gBfRtFlags & BfRtFlags_NoThreadExitWait) != 0)
  133. return;
  134. while (gLiveThreadCount != 0)
  135. {
  136. // Clear out any old done events
  137. gThreadsDoneEvent.WaitFor();
  138. }
  139. }
  140. BfInternalThread* Thread::SetupInternalThread()
  141. {
  142. BfInternalThread* internalThread;
  143. internalThread = new BfInternalThread();
  144. SetInternalThread(internalThread);
  145. return internalThread;
  146. }
  147. void Thread::ManualThreadInit()
  148. {
  149. #ifdef BF_THREAD_TLS
  150. sCurrentThread = this;
  151. #else
  152. BfpTLS_SetValue(BfTLSManager::sInternalThreadKey, this);
  153. #endif
  154. BfInternalThread* internalThread = SetupInternalThread();
  155. internalThread->ManualThreadInit(this);
  156. }
  157. void Thread::StartInternal()
  158. {
  159. BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, 1);
  160. BfInternalThread* internalThread = SetupInternalThread();
  161. Beefy::AutoCrit autoCrit(internalThread->mCritSect);
  162. internalThread->mStarted = true;
  163. internalThread->mThread = this;
  164. #ifdef _WIN32
  165. internalThread->mThreadHandle = BfpThread_Create(CStartProc, (void*)this, GetMaxStackSize(), (BfpThreadCreateFlags)(BfpThreadCreateFlag_StackSizeReserve | BfpThreadCreateFlag_Suspended), &internalThread->mThreadId);
  166. SetInternalThread(internalThread);
  167. BfpThread_Resume(internalThread->mThreadHandle, NULL);
  168. #else
  169. internalThread->mThreadHandle = BfpThread_Create(CStartProc, (void*)this, GetMaxStackSize(), (BfpThreadCreateFlags)(BfpThreadCreateFlag_StackSizeReserve), &internalThread->mThreadId);
  170. SetInternalThread(internalThread);
  171. #endif
  172. }
  173. void Thread::ThreadStarted()
  174. {
  175. auto internalThread = GetInternalThread();
  176. internalThread->mCritSect.Unlock();
  177. }
  178. int Thread::GetThreadId()
  179. {
  180. return (int)GetInternalThread()->mThreadId;
  181. }
  182. void Thread::SetStackStart(void* ptr)
  183. {
  184. GetInternalThread()->mRunning = true;
  185. GetInternalThread()->mStackStart = (intptr)ptr;
  186. }
  187. void Thread::InternalFinalize()
  188. {
  189. auto internalThread = GetInternalThread();
  190. if (internalThread == NULL)
  191. return;
  192. bool wantsJoin = false;
  193. bool started = false;
  194. //
  195. {
  196. Beefy::AutoCrit autoCrit(internalThread->mCritSect);
  197. started = internalThread->mStarted;
  198. }
  199. if (started)
  200. internalThread->mStartedEvent.WaitFor();
  201. //
  202. {
  203. Beefy::AutoCrit autoCrit(internalThread->mCritSect);
  204. if ((!internalThread->mDone) && (internalThread->mJoinOnDelete))
  205. {
  206. if (this != BfGetCurrentThread())
  207. {
  208. wantsJoin = true;
  209. }
  210. }
  211. }
  212. if (wantsJoin)
  213. JoinInternal(0);
  214. bool wantsDelete = false;
  215. //
  216. {
  217. Beefy::AutoCrit autoCrit(internalThread->mCritSect);
  218. if (!internalThread->mDone)
  219. {
  220. // We need to let the internal thread delete itself when it's done...
  221. internalThread->mThread = NULL;
  222. }
  223. else
  224. {
  225. wantsDelete = true;
  226. }
  227. SetInternalThread(NULL);
  228. }
  229. if (internalThread->mIsManualInit)
  230. wantsDelete = true;
  231. if (wantsDelete)
  232. delete internalThread;
  233. }
  234. bool Thread::IsBackgroundNative()
  235. {
  236. return false;
  237. }
  238. void Thread::SetBackgroundNative(bool isBackground)
  239. {
  240. }
  241. int Thread::GetThreadStateNative()
  242. {
  243. return 0;
  244. }
  245. void Thread::InformThreadNameChange(String* name)
  246. {
  247. BfpThread_SetName(GetInternalThread()->mThreadHandle, (name != NULL) ? name->CStr() : "", NULL);
  248. }
  249. void Thread::MemoryBarrier()
  250. {
  251. BF_FULL_MEMORY_FENCE();
  252. }