From c21be1eea1f50e68180c4a8e65161b4da9fcdae9 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 18 Jan 2025 17:40:48 -0800 Subject: [PATCH] Implemented IsBackground. Added GC.Disable --- BeefLibs/corlib/src/GC.bf | 3 ++ BeefLibs/corlib/src/Threading/Thread.bf | 49 +++++++++++++++---------- BeefRT/dbg/gc.cpp | 11 ++++++ BeefRT/dbg/gc.h | 4 +- BeefRT/rt/Thread.cpp | 24 ++++++++++-- BeefRT/rt/Thread.h | 2 + 6 files changed, 69 insertions(+), 24 deletions(-) diff --git a/BeefLibs/corlib/src/GC.bf b/BeefLibs/corlib/src/GC.bf index 6d8bed7e..2d2e6478 100644 --- a/BeefLibs/corlib/src/GC.bf +++ b/BeefLibs/corlib/src/GC.bf @@ -108,6 +108,8 @@ namespace System [CallingConvention(.Cdecl)] private extern static void Init(); [CallingConvention(.Cdecl)] + public extern static void Disable(); + [CallingConvention(.Cdecl)] public extern static void Collect(bool async = true); [CallingConvention(.Cdecl)] private extern static void StopCollecting(); @@ -136,6 +138,7 @@ namespace System [CallingConvention(.Cdecl)] public extern static void ExcludeThreadId(int thereadId); #else + public static void Disable() {} public static void Collect(bool async = true) {} private static void MarkAllStaticMembers() {} public static void DebugDumpLeaks() {} diff --git a/BeefLibs/corlib/src/Threading/Thread.bf b/BeefLibs/corlib/src/Threading/Thread.bf index 265d61ec..8c301c63 100644 --- a/BeefLibs/corlib/src/Threading/Thread.bf +++ b/BeefLibs/corlib/src/Threading/Thread.bf @@ -21,8 +21,9 @@ namespace System.Threading bool mAutoDelete = true; bool mJoinOnDelete; + bool mIsBackground; - static Monitor sMonitor = new .() ~ delete _; + static Monitor sMonitor = new .() ~ DeleteAndNullify!(_); static Event sOnExit ~ _.Dispose(); Event mOnExit ~ _.Dispose(); @@ -86,6 +87,8 @@ namespace System.Threading thread.InformThreadNameChange(thread.mName); if (thread.mPriority != .Normal) thread.SetPriorityNative((.)thread.mPriority); + if (thread.mIsBackground) + thread.SetBackgroundNative(thread.mIsBackground); int32 stackStart = 0; thread.SetStackStart((void*)&stackStart); @@ -239,27 +242,27 @@ namespace System.Threading } } - public void Start() - { - StartInternal(); - } + public void Start() + { + StartInternal(); + } public void Start(bool autoDelete) { mAutoDelete = autoDelete; Start(); } - - public void Start(Object parameter) - { - if (mDelegate is ThreadStart) + + public void Start(Object parameter) { - Runtime.FatalError(); + if (mDelegate is ThreadStart) + { + Runtime.FatalError(); + } + mThreadStartArg = parameter; + StartInternal(); } - mThreadStartArg = parameter; - StartInternal(); - } - + public void Start(Object parameter, bool autoDelete) { mAutoDelete = autoDelete; @@ -384,10 +387,13 @@ namespace System.Threading public ~this() { - using (sMonitor.Enter()) + if (sMonitor != null) { - mOnExit(); - sOnExit(); + using (sMonitor.Enter()) + { + mOnExit(); + sOnExit(); + } } if (mJoinOnDelete) @@ -403,8 +409,13 @@ namespace System.Threading public bool IsBackground { - get { return IsBackgroundNative(); } - set { SetBackgroundNative(value); } + get { return mIsBackground; } + set + { + mIsBackground = value; + if (mInternalThread != 0) + SetBackgroundNative(mIsBackground); + } } public void SetJoinOnDelete(bool joinOnDelete) diff --git a/BeefRT/dbg/gc.cpp b/BeefRT/dbg/gc.cpp index 07ecf378..e74cce25 100644 --- a/BeefRT/dbg/gc.cpp +++ b/BeefRT/dbg/gc.cpp @@ -2180,6 +2180,12 @@ void BFGC::AddPendingThread(BfInternalThread* internalThread) mPendingThreads.TryAdd(internalThread->mThreadId, internalThread); } +void BFGC::Disable() +{ + StopCollecting(); + mGracelessShutdown = true; +} + void BFGC::Shutdown() { if (mShutdown) @@ -2896,6 +2902,11 @@ void GC::RemoveStackMarkableObject(Object* obj) gBFGC.RemoveStackMarkableObject(obj); } +void GC::Disable() +{ + gBFGC.Disable(); +} + void GC::Shutdown() { gBFGC.Shutdown(); diff --git a/BeefRT/dbg/gc.h b/BeefRT/dbg/gc.h index 130605b6..6151a9a7 100644 --- a/BeefRT/dbg/gc.h +++ b/BeefRT/dbg/gc.h @@ -397,6 +397,7 @@ public: void AddStackMarkableObject(bf::System::Object* obj); void RemoveStackMarkableObject(bf::System::Object* obj); void AddPendingThread(BfInternalThread* internalThread); + void Disable(); void Shutdown(); void InitDebugDump(); void EndDebugDump(); @@ -474,7 +475,8 @@ namespace bf BFRT_EXPORT static void AddPendingThread(void* internalThreadInfo); public: - BFRT_EXPORT static void Shutdown(); + BFRT_EXPORT static void Disable(); + BFRT_EXPORT static void Shutdown(); BFRT_EXPORT static void Collect(bool async); BFRT_EXPORT static void Report(); BFRT_EXPORT static void Mark(Object* obj); diff --git a/BeefRT/rt/Thread.cpp b/BeefRT/rt/Thread.cpp index b006c372..93b0ab84 100644 --- a/BeefRT/rt/Thread.cpp +++ b/BeefRT/rt/Thread.cpp @@ -17,6 +17,7 @@ BF_TLS_DECLSPEC Thread* Thread::sCurrentThread; #endif static volatile int gLiveThreadCount; +static volatile int gBackgroundThreadCount; static Beefy::SyncEvent gThreadsDoneEvent; #ifdef BF_PLATFORM_WINDOWS @@ -132,8 +133,12 @@ static void BF_CALLTYPE CStartProc(void* threadParam) bool isAutoDelete = gBfRtCallbacks.Thread_IsAutoDelete(thread); gBfRtCallbacks.Thread_ThreadProc(thread); - bool isLastThread = BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, -1) == 1; + + 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; @@ -158,7 +163,7 @@ static void BF_CALLTYPE CStartProc(void* threadParam) delete internalThread; if (isLastThread) - gThreadsDoneEvent.Set(false); + gThreadsDoneEvent.Set(false); //printf("Thread stopped\n"); } @@ -168,7 +173,7 @@ void BfInternalThread::WaitForAllDone() if ((gBfRtFlags & BfRtFlags_NoThreadExitWait) != 0) return; - while (gLiveThreadCount != 0) + while (gLiveThreadCount > gBackgroundThreadCount) { // Clear out any old done events gThreadsDoneEvent.WaitFor(); @@ -303,12 +308,23 @@ void Thread::InternalFinalize() bool Thread::IsBackgroundNative() { - return false; + 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() diff --git a/BeefRT/rt/Thread.h b/BeefRT/rt/Thread.h index 22ea4d93..a074240d 100644 --- a/BeefRT/rt/Thread.h +++ b/BeefRT/rt/Thread.h @@ -111,6 +111,7 @@ public: bool mStarted; bool mJoinOnDelete; bool mIsManualInit; + bool mIsBackground; BfpThread* mThreadHandle; intptr mThreadId; Beefy::CritSect mCritSect; @@ -126,6 +127,7 @@ public: mIsSuspended = false; mJoinOnDelete = true; mIsManualInit = false; + mIsBackground = false; mStackStart = 0; mThreadId = 0; }