123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- #include "BeefySysLib/Common.h"
- #include "BfObjects.h"
- #include "Thread.h"
- //#include "ThreadLocalStorage.h"
- #include "StompAlloc.h"
- //#include <crtdbg.h>
- //#define USE_STOMP_ALLOC
- #undef MemoryBarrier
- using namespace bf::System;
- using namespace bf::System::Threading;
- #ifdef BF_THREAD_TLS
- BF_TLS_DECLSPEC Thread* Thread::sCurrentThread;
- #endif
- static volatile int gLiveThreadCount;
- static volatile int gBackgroundThreadCount;
- static Beefy::SyncEvent gThreadsDoneEvent;
- #ifdef BF_PLATFORM_WINDOWS
- extern DWORD gBfTLSKey;
- #else
- extern pthread_key_t gBfTLSKey;
- #endif
- bf::System::Threading::Thread* BfGetCurrentThread()
- {
- #ifdef BF_THREAD_TLS
- return Thread::sCurrentThread;
- #else
- Thread* internalThread = (Thread*)BfpTLS_GetValue(BfTLSManager::sInternalThreadKey);
- return internalThread;
- #endif
- }
- void Thread::Suspend()
- {
- BfpThread_Suspend(GetInternalThread()->mThreadHandle, NULL);
- }
- void Thread::Resume()
- {
- BfpThread_Resume(GetInternalThread()->mThreadHandle, NULL);
- }
- void Thread::SetJoinOnDelete(bool joinOnDelete)
- {
- auto internalThread = GetInternalThread();
- Beefy::AutoCrit autoCrit(internalThread->mCritSect);
- internalThread->mJoinOnDelete = joinOnDelete;
- }
- int Thread::GetPriorityNative()
- {
- return (int)BfpThread_GetPriority(GetInternalThread()->mThreadHandle, NULL) + 2;
- }
- void Thread::SetPriorityNative(int priority)
- {
- return BfpThread_SetPriority(GetInternalThread()->mThreadHandle, (BfpThreadPriority)(priority - 2), NULL);
- }
- bool Thread::GetIsAlive()
- {
- if (GetInternalThread() == NULL)
- return false;
- bool success = BfpThread_WaitFor(GetInternalThread()->mThreadHandle, 0);
- return !success;
- }
- bool Thread::GetIsThreadPoolThread()
- {
- return false;
- }
- bool Thread::JoinInternal(int millisecondsTimeout)
- {
- auto internalThread = GetInternalThread();
- if (internalThread == NULL)
- return true;
- bool success = BfpThread_WaitFor(internalThread->mThreadHandle, millisecondsTimeout);
- return success;
- }
- void Thread::SleepInternal(int millisecondsTimeout)
- {
- BfpThread_Sleep(millisecondsTimeout);
- }
- void Thread::SpinWaitInternal(int iterations)
- {
- BF_COMPILER_FENCE();
- BF_SPINWAIT_NOP();
- }
- bool Thread::YieldInternal()
- {
- return BfpThread_Yield();
- }
- Thread* Thread::GetCurrentThreadNative()
- {
- return BfGetCurrentThread();
- }
- unsigned long Thread::GetProcessDefaultStackSize()
- {
- return 0;
- }
- static void BF_CALLTYPE CStartProc(void* threadParam)
- {
- Thread* thread = (Thread*)threadParam;
- #ifdef BF_THREAD_TLS
- Thread::sCurrentThread = thread;
- #else
- BfpTLS_SetValue(BfTLSManager::sInternalThreadKey, thread);
- #endif
- auto internalThread = thread->GetInternalThread();
- // Hold lock until we get ThreadStarted callback
- internalThread->mCritSect.Lock();
- internalThread->mStartedEvent.Set(true);
- internalThread->mThreadHandle = BfpThread_GetCurrent();
- internalThread->mStackStart = (intptr)&thread;
- internalThread->ThreadStarted();
- bool isAutoDelete = gBfRtCallbacks.Thread_IsAutoDelete(thread);
- gBfRtCallbacks.Thread_ThreadProc(thread);
-
- if (internalThread->mIsBackground)
- BfpSystem_InterlockedExchangeAdd32((uint32*)&gBackgroundThreadCount, -1);
- bool isLastThread = (int32)BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, -1) <= gBackgroundThreadCount + 1;
-
- //printf("Stopping thread\n");
- bool wantsDelete = false;
- //
- {
- internalThread->ThreadStopped();
- Beefy::AutoCrit autoCrit(internalThread->mCritSect);
- if (isAutoDelete)
- gBfRtCallbacks.Thread_AutoDelete(thread);
- internalThread->mDone = true;
- if (internalThread->mThread == NULL)
- {
- // If the thread was already deleted then we need to delete ourselves now
- wantsDelete = true;
- }
- }
- if (wantsDelete)
- delete internalThread;
- if (isLastThread)
- gThreadsDoneEvent.Set(false);
- //printf("Thread stopped\n");
- }
- void BfInternalThread::WaitForAllDone()
- {
- if ((gBfRtFlags & BfRtFlags_NoThreadExitWait) != 0)
- return;
- while (gLiveThreadCount > gBackgroundThreadCount)
- {
- // Clear out any old done events
- gThreadsDoneEvent.WaitFor();
- }
- }
- BfInternalThread* Thread::SetupInternalThread()
- {
- BfInternalThread* internalThread;
- internalThread = new BfInternalThread();
- SetInternalThread(internalThread);
- return internalThread;
- }
- void Thread::ManualThreadInit()
- {
- #ifdef BF_THREAD_TLS
- sCurrentThread = this;
- #else
- BfpTLS_SetValue(BfTLSManager::sInternalThreadKey, this);
- #endif
- BfInternalThread* internalThread = SetupInternalThread();
- internalThread->ManualThreadInit(this);
- }
- void Thread::StartInternal()
- {
- BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, 1);
- BfInternalThread* internalThread = SetupInternalThread();
- Beefy::AutoCrit autoCrit(internalThread->mCritSect);
- internalThread->mStarted = true;
- internalThread->mThread = this;
- #ifdef _WIN32
- internalThread->mThreadHandle = BfpThread_Create(CStartProc, (void*)this, GetMaxStackSize(), (BfpThreadCreateFlags)(BfpThreadCreateFlag_StackSizeReserve | BfpThreadCreateFlag_Suspended), &internalThread->mThreadId);
- SetInternalThread(internalThread);
- BfpThread_Resume(internalThread->mThreadHandle, NULL);
- #else
- internalThread->mThreadHandle = BfpThread_Create(CStartProc, (void*)this, GetMaxStackSize(), (BfpThreadCreateFlags)(BfpThreadCreateFlag_StackSizeReserve), &internalThread->mThreadId);
- SetInternalThread(internalThread);
- #endif
- }
- void Thread::RequestExitNotify()
- {
- // Do we already have implicit exiting notification?
- if (BfGetCurrentThread() != NULL)
- return;
- #ifdef BF_PLATFORM_WINDOWS
- FlsSetValue(gBfTLSKey, (void*)&gBfRtCallbacks);
- #else
- pthread_setspecific(gBfTLSKey, (void*)&gBfRtCallbacks);
- #endif
- }
- void Thread::ThreadStarted()
- {
- auto internalThread = GetInternalThread();
- internalThread->mCritSect.Unlock();
- }
- intptr Thread::GetThreadId()
- {
- return GetInternalThread()->mThreadId;
- }
- void Thread::SetStackStart(void* ptr)
- {
- GetInternalThread()->mRunning = true;
- GetInternalThread()->mStackStart = (intptr)ptr;
- }
- void Thread::InternalFinalize()
- {
- auto internalThread = GetInternalThread();
- if (internalThread == NULL)
- return;
- bool wantsJoin = false;
- bool started = false;
- //
- {
- Beefy::AutoCrit autoCrit(internalThread->mCritSect);
- started = internalThread->mStarted;
- }
- if (started)
- internalThread->mStartedEvent.WaitFor();
- //
- {
- Beefy::AutoCrit autoCrit(internalThread->mCritSect);
- if ((!internalThread->mDone) && (internalThread->mJoinOnDelete))
- {
- if (this != BfGetCurrentThread())
- {
- wantsJoin = true;
- }
- }
- }
- if (wantsJoin)
- JoinInternal(0);
- bool wantsDelete = false;
- //
- {
- Beefy::AutoCrit autoCrit(internalThread->mCritSect);
- if (!internalThread->mDone)
- {
- // We need to let the internal thread delete itself when it's done...
- internalThread->mThread = NULL;
- }
- else
- {
- wantsDelete = true;
- }
- SetInternalThread(NULL);
- }
- if (internalThread->mIsManualInit)
- wantsDelete = true;
- if (wantsDelete)
- delete internalThread;
- }
- bool Thread::IsBackgroundNative()
- {
- auto internalThread = GetInternalThread();
- if (internalThread == NULL)
- return false;
- return internalThread->mIsBackground;
- }
- void Thread::SetBackgroundNative(bool isBackground)
- {
- auto internalThread = GetInternalThread();
- if (internalThread == NULL)
- return;
- if (isBackground != internalThread->mIsBackground)
- {
- internalThread->mIsBackground = isBackground;
- BfpSystem_InterlockedExchangeAdd32((uint32*)&gBackgroundThreadCount, isBackground ? 1 : -1);
- }
- }
- int Thread::GetThreadStateNative()
- {
- return 0;
- }
- void Thread::InformThreadNameChange(String* name)
- {
- Beefy::String nameStr;
- if (name != NULL)
- nameStr = name->ToStringView();
- BfpThread_SetName(GetInternalThread()->mThreadHandle, nameStr.c_str(), NULL);
- }
- void Thread::MemoryBarrier()
- {
- BF_FULL_MEMORY_FENCE();
- }
|