AuroraRuntime/Include/Aurora/Async/IThreadPool.hpp

116 lines
4.8 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IThreadPool.hpp
Date: 2021-11-1
Author: Reece
***/
#pragma once
namespace Aurora::IO::Loop
{
struct ILoopQueue;
struct ILoopSource;
}
namespace Aurora::Async
{
AUE_DEFINE(ERunMode,
(
eLowLatencyYield, // uses high perf cond var + yield + trylock
eLowLatencyFreqKernel, // uses high perf cond var + timeout(freqency)
eEfficient // delegates sleep to the kernel once kernel objects are scheduled
));
struct RunMode
{
ERunMode mode;
AuUInt16 freqMsTick;
};
struct IThreadPool
{
// Spawning
virtual bool Spawn(WorkerId_t workerId) = 0;
// Event runner threads release the thread pool upon encountering a zero work condition,
// allowing for a clean exit out of event driven apps, without the headache of carefully
// chaining together exit callbacks.
//
// Applications that aren't designed around an event driven model should set/keep running
// mode to false to keep-alive the around during work exhaustion
//
// tl'dr: runner = true, async app; runner = false, thread pool
virtual void SetRunningMode(bool bEventRunning) = 0;
// Converts the current thread into an async thread
// Use with RunOnce, Poll
virtual bool Create(WorkerId_t workerId) = 0;
//virtual bool CreateAndRun(WorkerId_t workerId) = 0;
// @returns any threads with runner = true
virtual bool InRunnerMode() = 0;
// Manual execution for ::Create() users and those wishing to nest ticks
virtual bool Poll() = 0;
virtual bool RunOnce() = 0;
virtual bool Run() = 0;
//
virtual void Shutdown() = 0;
virtual bool Exiting() = 0;
//
virtual AuSPtr<IWorkItem> NewWorkItem(const WorkerId_t &worker,
const AuSPtr<IWorkItemHandler> &task,
bool bSupportsBlocking = false) = 0;
virtual AuSPtr<IWorkItem> NewFence() = 0;
//
virtual Threading::Threads::ThreadShared_t ResolveHandle(WorkerId_t) = 0;
//
virtual AuBST<ThreadGroup_t, AuList<ThreadId_t>> GetThreads() = 0;
//
virtual WorkerId_t GetCurrentThread() = 0;
// Synchronization
// Note: syncing to yourself will nullify requireSignal to prevent deadlock conditions
virtual bool Sync(WorkerId_t workerId,
AuUInt32 timeoutMs = 0,
bool bRequireSignal = false) = 0;
virtual void Signal(WorkerId_t workerId) = 0;
virtual AuSPtr<IO::Loop::ILoopSource> WorkerToLoopSource(WorkerId_t id) = 0;
virtual void SyncAllSafe() = 0;
// Features
/**
* @brief
* @param id
* @param feature
* @param bDontBlockUntilComplete inverse of block until complete.
default: block until after IThreadFeature::Init
*/
virtual void AddFeature(WorkerId_t id,
AuSPtr<Threading::Threads::IThreadFeature> feature,
bool bDontBlockUntilComplete = false) = 0;
// Debug
virtual void AssertInThreadGroup(ThreadGroup_t group) = 0;
virtual void AssertWorker(WorkerId_t id) = 0;
// AuIO overlapped-IO glue
virtual AuSPtr<IO::Loop::ILoopQueue> ToKernelWorkQueue() = 0;
virtual AuSPtr<IO::Loop::ILoopQueue> ToKernelWorkQueue(WorkerId_t workerId) = 0;
virtual void UpdateWorkMode(WorkerId_t workerId, RunMode mode) = 0;
virtual ERunMode GetCurrentThreadRunMode() = 0;
virtual ERunMode GetThreadRunMode(WorkerId_t workerId) = 0;
};
}