← API Reference Class

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.

Warning

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

#using thread_pointer = std::unique_ptr< Thread >

Protected Attributes

#context_pointer m_Ctx {nullptr}protected
#std::unique_ptr< std::thread > m_Thread {nullptr}protected
#std::thread::id m_ThreadIdprotected
#std::string m_Nameprotected
#bool m_Daemon {false}protected

Static Protected Attributes

#static std::uint64_t s_ThreadCounter {0}protected

Private Member Functions

#void _Run()private

Protected Member Functions

#virtual void Run(context_pointer &)=0protected

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.

#virtual void TearDown()protected

Public Member Functions

#Thread(context_pointer inCtx=nullptr)
#Thread(std::string const &inName, context_pointer inCtx=nullptr, bool inDaemon=false)
#Thread(Thread const &)=delete
#Thread & operator=(Thread const &)=delete
#Thread(Thread &&)=default
#Thread & operator=(Thread &&)=default
#virtual ~Thread()
#bool Joinable() const noexcept

Checks 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 noexcept
#bool Started() const noexcept
#const std::string & GetName() const noexcept
#std::thread::id GetThreadId() const noexcept
#void 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.