asge::concurrent::Thread abstract
Abstract base class representing a managed, cancellable thread.
#include <Thread.hpp>Inherited by asge::concurrent::_internal::ThreadImpl< _Callable, _Args >, asge::concurrent::_internal::Worker, asge::filesystem::_linux::FileWatcher.
Inheritance
classDiagram
class N1["asge::concurrent::Thread"]
class N2["asge::concurrent::_internal::ThreadImpl"]
class N3["asge::concurrent::_internal::Worker"]
class N4["asge::filesystem::_linux::FileWatcher"]
N1 <|-- N2
N1 <|-- N3
N1 <|-- N4
click N1 href "classasge_1_1concurrent_1_1Thread.html"
click N2 href "classasge_1_1concurrent_1_1__internal_1_1ThreadImpl.html"
click N3 href "classasge_1_1concurrent_1_1__internal_1_1Worker.html"
click N4 href "classasge_1_1filesystem_1_1__linux_1_1FileWatcher.html"
Wraps a std::thread and provides a structured lifecycle — start, run, cancel, teardown — built around a virtual Run() method that subclasses override to implement their logic. The thread loop itself is managed internally: Run() is called repeatedly until the context is cancelled, keeping subclass implementations focused purely on per-iteration logic.
Cancellation is cooperative. Subclasses signal intent to stop by calling Cancel() on the ThreadContext passed to Run(). The loop exits cleanly after the current iteration completes, then TearDown() is invoked.
Threads can operate in two modes:
Joinable: the creating thread can wait for completion via Join().
Daemon: the thread is detached and runs independently until cancelled.
Each instance is assigned a unique name (defaulting to ASGE_Thread_N) used for identification and debugging. Copy is disabled since a thread represents a unique resource. Move is supported.
Every subclass MUST call Cancel() then Join() in its own destructor before returning. ~Thread() also does this, but only as a best-effort safety net — by the time a base-class destructor runs, the vtable has already reverted away from the derived override, so if the background thread is still mid-loop it can dispatch into Run()'s pure virtual slot in Thread and crash ("pure virtual function called"). Joining from the most-derived destructor is the only place guaranteed to run before that vtable switch happens.
Public Types
Protected Attributes
Static Protected Attributes
Private Member Functions
Protected Member Functions
Implements the internal thread logic.
This method must implement only the internal thread logic inside the thread loop, which is instead managed outside the particular thread implementation. Therefore, all other conditions that might be return the thread execution must be specified in this method. To cancel the thread, the Cancel function on the context shall be called.
Public Member Functions
Thread(context_pointer inCtx=nullptr)Thread(std::string const &inName, context_pointer inCtx=nullptr, bool inDaemon=false)Thread(Thread const &)=deleteThread(Thread &&)=defaultvirtual ~Thread()bool Joinable() const noexceptChecks if the thread is joinable.
A thread is joinable if it has started, if the internal pointer is not a null pointer (i.e., if the thread has been defined) and if the internal thread is joinable ( meaning that it is not a daemon).
bool Daemon() const noexceptbool Started() const noexceptconst std::string & GetName() const noexceptstd::thread::id GetThreadId() const noexceptvoid Join()void Detach()Detaches the running thread, marking it a daemon.
A no-op if the thread was never started, is already detached, or has already been joined. Safe to call regardless of whether the running thread's work has finished detach() only requires the underlying std::thread to still be joinable, not still executing.
void Start()void Cancel()template<typename _Callable, typename... _Args> thread_pointer Start(bool inDaemon, context_pointer inCtx, _Callable &&inFunc, _Args &&...inArgs)Static Public Member Functions
template<typename _Callable, typename... _Args> static thread_pointer Start(bool, context_pointer, _Callable &&, _Args &&...)Starts and create a new thread from an input function.
The input function can take a variadic number of input parameters, but the first input parameter must always be a ThreadContext reference.