/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: ThreadPool.hpp Date: 2021-10-30 Author: Reece ***/ #pragma once #include "IThreadPoolInternal.hpp" namespace Aurora::Async { struct GroupState; struct ThreadState; struct IAsyncRunnable; //class WorkItem; struct ThreadPool : IThreadPool, IThreadPoolInternal, AuEnableSharedFromThis { ThreadPool(); // IThreadPoolInternal bool WaitFor(WorkerPId_t unlocker, const AuSPtr &primitive, AuUInt32 ms) override; bool WaitFor(WorkerId_t unlocker, const AuSPtr &primitive, AuUInt32 ms); void Run(WorkerId_t target, AuSPtr runnable) override; void Run(WorkerId_t target, AuSPtr runnable, bool bIncrement); IThreadPool *ToThreadPool() override; // IThreadPool virtual bool Spawn(WorkerId_t workerId) override; virtual void SetRunningMode(bool eventRunning) override; virtual bool Create(WorkerId_t workerId) override; virtual bool InRunnerMode() override; virtual bool Poll() override; virtual bool RunOnce() override; virtual bool Run() override; virtual void Shutdown() override; virtual bool Exiting() override; virtual AuUInt32 PollAndCount(bool bStrict = true) override; virtual AuUInt32 RunAllPending() override; virtual AuSPtr NewWorkItem(const WorkerId_t &worker, const AuSPtr &task) override; virtual AuSPtr NewWorkFunction(const WorkerId_t &worker, AuVoidFunc callback) override; virtual AuSPtr NewFence() override; virtual Threading::Threads::ThreadShared_t ResolveHandle(WorkerId_t) override; virtual AuBST> GetThreads() override; virtual WorkerId_t GetCurrentThread() override; virtual AuSPtr GetIOProcessor(WorkerId_t id) override; virtual AuSPtr GetIONetInterface(WorkerId_t pid) override; virtual AuSPtr GetIONetWorker(WorkerId_t id) override; virtual AuSPtr GetIOGroup(WorkerId_t id) override; virtual bool Sync(WorkerId_t workerId, AuUInt32 timeoutMs, bool requireSignal) override; virtual void Signal(WorkerId_t workerId) override; virtual void Wakeup(WorkerId_t workerId) override; virtual AuSPtr WorkerToLoopSource(WorkerId_t id) override; virtual void SyncAllSafe() override; virtual void AddFeature(WorkerId_t id, AuSPtr feature, bool async) override; virtual void AssertInThreadGroup(ThreadGroup_t group) override; virtual void AssertWorker(WorkerId_t id) override; virtual AuSPtr ToKernelWorkQueue() override; virtual AuSPtr ToKernelWorkQueue(WorkerId_t workerId) override; virtual AuSPtr GetShutdownEvent() override; virtual void AddDependency(AuSPtr pPool) override; virtual void IncrementAbortFenceOnPool() override; virtual void IncrementAbortFenceOnWorker(WorkerId_t workerId) override; virtual AuUInt64 QueryAbortFence(AuOptional optWorkerId) override; virtual bool QueryShouldAbort(AuOptional optWorkerId, AuUInt64 uFenceMagic) override; bool IsSelfDepleted(const AuSPtr &state); bool IsDepleted(const AuSPtr &state); //virtual bool ScheduleLoopSource(const AuSPtr &loopSource, WorkerId_t workerId, AuUInt32 timeout, const AuConsumer, bool> &callback) override; // Internal API bool Spawn(WorkerId_t workerId, bool create); bool InternalRunOne(AuSPtr, bool block, bool bUntilWork, AuUInt32 &uCount); bool PollInternal(AuSPtr, bool block, bool bUntilWork, AuUInt32 &uCount); #if defined(__AUHAS_COROUTINES_CO_AWAIT) && defined(AU_LANG_CPP_20_) AuVoidTask PollInternal_ForceCoRoutine(AuSPtr, bool block, bool bUntilWork, AuUInt32 &uCount, bool &bRet); #endif bool PollInternal_Base(AuSPtr, bool block, bool bUntilWork, AuUInt32 &uCount); size_t GetThreadWorkersCount(ThreadGroup_t group); virtual void CleanUpWorker(WorkerId_t wid) {}; virtual void CleanWorkerPoolReservedZeroFree() {}; // calls shutdown under async apps // Secret old fiber api bool CtxYield(); int CtxPollPush(); void CtxPollReturn(const AuSPtr &state, int status, bool hitTask); // TLS handle struct WorkerWPId_t : WorkerId_t { WorkerWPId_t() {} WorkerWPId_t(const WorkerPId_t &ref) : WorkerId_t(ref.first, ref.second), pool(ref.GetPool()) {} AuWPtr pool; }; AuThreads::TLSVariable tlsWorkerId; AuSPtr GetThreadHandle(WorkerId_t id) override; private: // TODO: BarrierMultiple bool Barrier(WorkerId_t, AuUInt32 ms, bool requireSignal, bool drop); protected: void Entrypoint(WorkerId_t id); private: void EarlyExitTick(); void ThisExiting(); AuSPtr GetGroup(ThreadGroup_t type); AuSPtr GetThreadState(); AuSPtr GetThreadStateNoWarn(); AuSPtr GetThreadStateLocal(); AuList> GetThreadHandles(WorkerId_t id); AuSPtr threadGroups_[255]; AuUInt32 shuttingdown_ {}; bool shutdown {}; AuRWRenterableLock rwlock_; AuThreading::IWaitable *pRWReadView {}; AuEvent shutdownEvent_; bool runnersRunning_ {}; AuList> listWeakDeps_; AuList> listWeakDepsParents_; // TODO: fallback heap AuMemory::AllocHeapUnique_t pHeap { AuMemory::AllocHeapUnique(512 * 1024) }; friend struct KeepGroupAlive; }; }