diff --git a/Include/Aurora/Async/IThreadPool.hpp b/Include/Aurora/Async/IThreadPool.hpp index 8ffd6ab5..876a1c75 100644 --- a/Include/Aurora/Async/IThreadPool.hpp +++ b/Include/Aurora/Async/IThreadPool.hpp @@ -123,5 +123,8 @@ namespace Aurora::Async virtual void UpdateWorkMode(WorkerId_t workerId, RunMode mode) = 0; virtual ERunMode GetCurrentThreadRunMode() = 0; virtual ERunMode GetThreadRunMode(WorkerId_t workerId) = 0; + + // + virtual AuSPtr GetShutdownEvent() = 0; }; } \ No newline at end of file diff --git a/Source/Async/AsyncApp.cpp b/Source/Async/AsyncApp.cpp index 53a1ae06..16609f97 100644 --- a/Source/Async/AsyncApp.cpp +++ b/Source/Async/AsyncApp.cpp @@ -47,6 +47,11 @@ namespace Aurora::Async Console::Commands::UpdateDispatcher(WorkerPId_t(GetSharedAsyncApp(), id)); } + AuSPtr AsyncApp::GetShutdownEvent() + { + return ThreadPool::GetShutdownEvent(); + } + void AsyncApp::CleanUpWorker(WorkerId_t id) { // This shouldn't be a problem; however, we're going to handle the one edge case where diff --git a/Source/Async/AsyncApp.hpp b/Source/Async/AsyncApp.hpp index 4978332f..3c150688 100644 --- a/Source/Async/AsyncApp.hpp +++ b/Source/Async/AsyncApp.hpp @@ -16,7 +16,7 @@ namespace Aurora::Async inline struct AsyncApp *gAsyncApp; - struct AsyncApp : public IAsyncApp, ThreadPool + struct AsyncApp : IAsyncApp, ThreadPool { bool Spawn(WorkerId_t workerId) override; void SetRunningMode(bool eventRunning) override; @@ -53,6 +53,8 @@ namespace Aurora::Async void Main() override; void SetConsoleCommandDispatcher(WorkerId_t id) override; + AuSPtr GetShutdownEvent() override; + void CleanUpWorker(WorkerId_t wid) override; void CleanWorkerPoolReservedZeroFree() override; diff --git a/Source/Async/ThreadPool.cpp b/Source/Async/ThreadPool.cpp index 68deebfd..ca6186a1 100644 --- a/Source/Async/ThreadPool.cpp +++ b/Source/Async/ThreadPool.cpp @@ -41,10 +41,8 @@ namespace Aurora::Async // - ThreadPool::ThreadPool() + ThreadPool::ThreadPool() : shutdownEvent_(false, false, true) { - this->rwlock_ = AuThreadPrimitives::RWLockUnique(); - SysAssert(static_cast(this->rwlock_), "Couldn't initialize ThreadPool. Unable to allocate an RWLock"); } // internal pool interface @@ -267,19 +265,22 @@ namespace Aurora::Async { bool ranOnce {}; + auto pJobRunner = GetThreadStateNoWarn(); + + if (!pJobRunner) + { + this->shutdownEvent_->LockMS(0); + return true; + } + gCurrentPool = AuWeakFromThis(); auto auThread = AuThreads::GetThread(); - auto job = GetThreadState(); - - if (!job) - { - SysPushErrorUninitialized("Not an async thread"); - } + while ((!auThread->Exiting()) && (!this->shutdown) && - (!job->bBreakEarly)) + (!pJobRunner->bBreakEarly)) { AuUInt32 uCount {}; @@ -299,10 +300,11 @@ namespace Aurora::Async bool ThreadPool::InternalRunOne(bool block, AuUInt32 &uCount) { - auto state = GetThreadState(); + auto state = GetThreadStateNoWarn(); if (!state) { SysPushErrorUninitialized("Not an async thread"); + return false; } bool success {}; @@ -389,6 +391,7 @@ namespace Aurora::Async return success; } + // TODO: rewrite queues bool ThreadPool::PollInternal(bool block, AuUInt32 &uCount) { auto state = GetThreadState(); @@ -660,6 +663,8 @@ namespace Aurora::Async return true; } + // While much of this subsystem needs good rewrite, under no circumstance should the shutdown process be "simpified" or "cleaned up" + // This is our expected behaviour. Any changes will likely introduce hard to catch bugs across various softwares and exit conditions. void ThreadPool::Shutdown() { auto trySelfPid = AuAsync::GetCurrentWorkerPId(); @@ -789,6 +794,7 @@ namespace Aurora::Async // Is dead flag this->shutdown = true; + this->shutdownEvent_->Set(); if (pLocalRunner) { @@ -1035,7 +1041,12 @@ namespace Aurora::Async return worker->runMode; } - // Unimplemented fiber hooks, 'twas used for science + AuSPtr ThreadPool::GetShutdownEvent() + { + return AuSPtr(AuSharedFromThis(), this->shutdownEvent_.AsPointer()); + } + + // Unimplemented fiber hooks, 'twas used for science. no longer in use int ThreadPool::CtxPollPush() { diff --git a/Source/Async/ThreadPool.hpp b/Source/Async/ThreadPool.hpp index 25511dd2..8c5a98db 100644 --- a/Source/Async/ThreadPool.hpp +++ b/Source/Async/ThreadPool.hpp @@ -79,6 +79,8 @@ namespace Aurora::Async virtual ERunMode GetCurrentThreadRunMode() override; virtual ERunMode GetThreadRunMode(WorkerId_t workerId) override; + virtual AuSPtr GetShutdownEvent() override; + //virtual bool ScheduleLoopSource(const AuSPtr &loopSource, WorkerId_t workerId, AuUInt32 timeout, const AuConsumer, bool> &callback) override; // Internal API @@ -135,7 +137,8 @@ namespace Aurora::Async ThreadDb_t threads_; AuUInt32 shuttingdown_ {}; bool shutdown {}; - AuThreadPrimitives::RWLockUnique_t rwlock_; + AuThreadPrimitives::RWLock rwlock_; + AuThreadPrimitives::Event shutdownEvent_; std::atomic_int tasksRunning_; bool runnersRunning_ {}; }; diff --git a/Source/AuRTEntrypoint.cpp b/Source/AuRTEntrypoint.cpp index 6b4cb522..6b6846e5 100644 --- a/Source/AuRTEntrypoint.cpp +++ b/Source/AuRTEntrypoint.cpp @@ -89,7 +89,21 @@ static void Init() Aurora::Hashing::InitHashing(); Aurora::Async::InitAsync(); gRuntimeRunLevel = 2; - + +#if defined(AURORA_PLATFORM_WIN32) + if (!gRuntimeConfig.console.asyncVSLog) + { + if (IsDebuggerPresent()) + { + AuLogWarn("A debugger is attached and RuntimeStartInfo::console.asyncVSLog is assigned false - log-lines will be flushed to Visual Studios output window immediately. Expect a slowdown. Do not benchmark."); + } + else + { + gRuntimeConfig.console.asyncVSLog = true; + } + } +#endif + Pump(); }