1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00
Beef/BeefRT/rt/Thread.cpp

328 lines
6.9 KiB
C++
Raw Normal View History

2019-08-23 11:56:54 -07:00
#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 Beefy::SyncEvent gThreadsDoneEvent;
2022-07-04 10:20:38 -07:00
#ifdef BF_PLATFORM_WINDOWS
extern DWORD gBfTLSKey;
#else
extern pthread_key_t gBfTLSKey;
#endif
2019-08-23 11:56:54 -07:00
bf::System::Threading::Thread* BfGetCurrentThread()
{
#ifdef BF_THREAD_TLS
return Thread::sCurrentThread;
#else
Thread* internalThread = (Thread*)BfpTLS_GetValue(BfTLSManager::sInternalThreadKey);
return internalThread;
#endif
}
2022-05-24 07:28:21 -07:00
void Thread::Suspend()
2019-08-23 11:56:54 -07:00
{
BfpThread_Suspend(GetInternalThread()->mThreadHandle, NULL);
}
2022-05-24 07:28:21 -07:00
void Thread::Resume()
2019-08-23 11:56:54 -07:00
{
BfpThread_Resume(GetInternalThread()->mThreadHandle, NULL);
}
void Thread::SetJoinOnDelete(bool joinOnDelete)
{
auto internalThread = GetInternalThread();
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
internalThread->mJoinOnDelete = joinOnDelete;
}
int Thread::GetPriorityNative()
{
2021-06-19 12:35:29 -07:00
return (int)BfpThread_GetPriority(GetInternalThread()->mThreadHandle, NULL) + 2;
2019-08-23 11:56:54 -07:00
}
void Thread::SetPriorityNative(int priority)
{
2021-06-19 12:35:29 -07:00
return BfpThread_SetPriority(GetInternalThread()->mThreadHandle, (BfpThreadPriority)(priority - 2), NULL);
2019-08-23 11:56:54 -07:00
}
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)
{
2019-10-15 17:27:09 -07:00
auto internalThread = GetInternalThread();
if (internalThread == NULL)
return true;
bool success = BfpThread_WaitFor(internalThread->mThreadHandle, millisecondsTimeout);
2019-08-23 11:56:54 -07:00
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();
2022-03-18 18:06:14 -07:00
// Hold lock until we get ThreadStarted callback
internalThread->mCritSect.Lock();
internalThread->mStartedEvent.Set(true);
2019-08-23 11:56:54 -07:00
internalThread->mThreadHandle = BfpThread_GetCurrent();
internalThread->mStackStart = (intptr)&thread;
internalThread->ThreadStarted();
2022-03-18 18:06:14 -07:00
2019-08-23 11:56:54 -07:00
bool isAutoDelete = gBfRtCallbacks.Thread_IsAutoDelete(thread);
gBfRtCallbacks.Thread_ThreadProc(thread);
bool isLastThread = BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, -1) == 1;
//printf("Stopping thread\n");
2022-03-18 18:06:14 -07:00
2019-08-23 11:56:54 -07:00
bool wantsDelete = false;
//
{
2022-07-04 10:20:38 -07:00
internalThread->ThreadStopped();
2019-08-23 11:56:54 -07:00
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
2022-03-18 18:06:14 -07:00
wantsDelete = true;
2019-08-23 11:56:54 -07:00
}
}
if (wantsDelete)
delete internalThread;
if (isLastThread)
gThreadsDoneEvent.Set(false);
//printf("Thread stopped\n");
}
void BfInternalThread::WaitForAllDone()
{
if ((gBfRtFlags & BfRtFlags_NoThreadExitWait) != 0)
return;
2019-08-23 11:56:54 -07:00
while (gLiveThreadCount != 0)
{
// 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;
2019-10-15 17:27:09 -07:00
#else
BfpTLS_SetValue(BfTLSManager::sInternalThreadKey, this);
2019-08-23 11:56:54 -07:00
#endif
BfInternalThread* internalThread = SetupInternalThread();
internalThread->ManualThreadInit(this);
}
void Thread::StartInternal()
{
BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, 1);
BfInternalThread* internalThread = SetupInternalThread();
2022-03-18 18:06:14 -07:00
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
internalThread->mStarted = true;
internalThread->mThread = this;
2020-08-31 14:16:58 -07:00
#ifdef _WIN32
internalThread->mThreadHandle = BfpThread_Create(CStartProc, (void*)this, GetMaxStackSize(), (BfpThreadCreateFlags)(BfpThreadCreateFlag_StackSizeReserve | BfpThreadCreateFlag_Suspended), &internalThread->mThreadId);
SetInternalThread(internalThread);
BfpThread_Resume(internalThread->mThreadHandle, NULL);
2020-08-31 14:16:58 -07:00
#else
internalThread->mThreadHandle = BfpThread_Create(CStartProc, (void*)this, GetMaxStackSize(), (BfpThreadCreateFlags)(BfpThreadCreateFlag_StackSizeReserve), &internalThread->mThreadId);
SetInternalThread(internalThread);
#endif
2019-08-23 11:56:54 -07:00
}
2022-07-04 10:20:38 -07:00
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
}
2022-03-18 18:06:14 -07:00
void Thread::ThreadStarted()
{
auto internalThread = GetInternalThread();
internalThread->mCritSect.Unlock();
}
2022-07-04 10:20:38 -07:00
intptr Thread::GetThreadId()
2019-08-23 11:56:54 -07:00
{
2022-07-04 10:20:38 -07:00
return GetInternalThread()->mThreadId;
2019-08-23 11:56:54 -07:00
}
void Thread::SetStackStart(void* ptr)
{
GetInternalThread()->mRunning = true;
GetInternalThread()->mStackStart = (intptr)ptr;
}
void Thread::InternalFinalize()
{
auto internalThread = GetInternalThread();
2019-10-15 17:27:09 -07:00
if (internalThread == NULL)
return;
2022-03-18 18:06:14 -07:00
2019-08-23 11:56:54 -07:00
bool wantsJoin = false;
2022-03-18 18:06:14 -07:00
bool started = false;
2019-08-23 11:56:54 -07:00
//
{
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
2022-03-18 18:06:14 -07:00
started = internalThread->mStarted;
}
if (started)
internalThread->mStartedEvent.WaitFor();
//
{
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
2019-08-23 11:56:54 -07:00
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);
}
2022-03-18 18:06:14 -07:00
if (internalThread->mIsManualInit)
wantsDelete = true;
2019-08-23 11:56:54 -07:00
if (wantsDelete)
delete internalThread;
}
bool Thread::IsBackgroundNative()
{
return false;
}
void Thread::SetBackgroundNative(bool isBackground)
{
}
int Thread::GetThreadStateNative()
{
return 0;
}
void Thread::InformThreadNameChange(String* name)
{
BfpThread_SetName(GetInternalThread()->mThreadHandle, (name != NULL) ? name->CStr() : "", NULL);
}
void Thread::MemoryBarrier()
{
BF_FULL_MEMORY_FENCE();
}