VLink  2.0.0
A high-performance communication middleware
vlink::MessageLoop Class Reference

Serial task dispatcher with selectable queue backend and bounded timer registry. More...

#include <message_loop.h>

Inheritance diagram for vlink::MessageLoop:
Collaboration diagram for vlink::MessageLoop:

Classes

struct  AliveState
 Lifetime gate shared with cross-thread observers. More...
 

Public Types

enum  Type : uint8_t { kNormalType = 0 , kLockfreeType = 1 , kPriorityType = 2 }
 Internal queue implementation type. More...
 
enum  Strategy : uint8_t { kOptimizationStrategy = 0 , kPopStrategy = 1 , kBlockStrategy = 2 }
 Back-pressure strategy applied when the bounded queue is at capacity. More...
 
enum  Priority : uint16_t {
  kNoPriority = 0 , kLowestPriority = 1 , kTimerPriority = 50 , kNormalPriority = 100 ,
  kHighestPriority = std::numeric_limits<uint16_t>::max()
}
 Built-in priority levels for kPriorityType loops; higher values dispatch first. More...
 
using Callback = MoveFunction< void()>
 Callback type for tasks and event handlers. More...
 

Public Member Functions

 MessageLoop ()
 Constructs a loop with the default kNormalType queue. More...
 
 MessageLoop (Type type)
 Constructs a loop with the given queue type. More...
 
virtual ~MessageLoop ()
 Destructor; requests quit and joins the dispatcher thread if needed. More...
 
void set_name (const std::string &name)
 Sets a human-readable name visible to profiling tools. More...
 
const std::string & get_name () const
 Returns the loop name set via set_name. More...
 
Type get_type () const
 Returns the queue type this loop was constructed with. More...
 
Strategy get_strategy () const
 Returns the active back-pressure strategy. More...
 
void set_strategy (Strategy strategy)
 Replaces the back-pressure strategy. More...
 
void register_begin_handler (Callback &&callback)
 Registers a callback fired once at loop thread startup. More...
 
void register_end_handler (Callback &&callback)
 Registers a callback fired once when the loop thread exits. More...
 
void register_idle_handler (Callback &&callback)
 Registers a callback fired every time the queue becomes empty. More...
 
bool run ()
 Runs the loop on the calling thread until quit is requested. More...
 
bool async_run ()
 Starts the loop on a new background thread. More...
 
bool spin ()
 Alias of run blocking the calling thread. More...
 
bool spin_once (bool block=true)
 Processes one batch of pending tasks and timers on the calling thread. More...
 
bool quit (bool force=false)
 Requests the loop to exit. More...
 
bool wait_for_quit (int ms=Timer::kInfinite, bool check=true)
 Waits until the loop has fully exited. More...
 
bool post_task (Callback &&callback)
 Posts a task for execution on the loop thread. More...
 
TaskHandle post_task_handle (Callback &&callback, const PostTaskOptions &options={})
 Tracked variant of post_task returning a TaskHandle. More...
 
bool post_task_with_priority (Callback &&callback, uint16_t priority)
 Posts a task with an explicit priority on a kPriorityType loop. More...
 
TaskHandle post_task_with_priority_handle (Callback &&callback, uint16_t priority, const PostTaskOptions &options={})
 Tracked variant of post_task_with_priority returning a TaskHandle. More...
 
template<typename CallbackT , typename = std::enable_if_t<!std::is_convertible_v<CallbackT, Schedule::RetCallback>>>
Schedule::Status exec_task (const Schedule::Config &config, CallbackT &&callback)
 Schedules a void-returning callable and returns a chainable Schedule::Status. More...
 
template<typename CallbackT , typename = std::enable_if_t<std::is_convertible_v<CallbackT, Schedule::RetCallback>>>
Schedule::RetStatus exec_task (const Schedule::Config &config, CallbackT &&callback)
 Schedules a bool-returning callable and returns a chainable Schedule::RetStatus. More...
 
bool wakeup ()
 Wakes the loop thread if it is suspended in its idle wait. More...
 
void reset_lockfree_capacity ()
 Recreates the lock-free queue, clearing all queued tasks and counters. More...
 
bool is_running () const
 Reports whether the loop is currently running. More...
 
bool is_ready_to_quit () const
 Reports whether quit has been requested and the loop is winding down. More...
 
bool is_busy () const
 Reports whether the loop is currently executing a task. More...
 
size_t get_task_count () const
 Returns the current pending task count. More...
 
virtual bool wait_for_idle (int ms=Timer::kInfinite, bool check=true)
 Waits until the loop has drained its queue and is not executing a task. More...
 
virtual size_t get_max_task_count () const
 Returns the maximum queue depth. More...
 
virtual size_t get_max_timer_count () const
 Returns the maximum number of timers that can be attached. More...
 
virtual uint32_t get_max_elapsed_time () const
 Returns the maximum allowed task execution time in milliseconds. More...
 
virtual bool is_in_same_thread () const
 Reports whether the calling thread is owned by this loop. More...
 
std::shared_ptr< AliveStateget_alive_state () const
 Returns the shared lifetime flag used by cross-thread bridges. More...
 
template<class FunctionT , class... ArgsT, typename ResultT = std::invoke_result_t<FunctionT, ArgsT...>>
std::future< ResultT > invoke_task (FunctionT &&function, ArgsT &&... args)
 Dispatches a callable to the loop thread and returns a std::future for the result. More...
 
template<class FunctionT , class... ArgsT, typename ResultT = std::invoke_result_t<FunctionT, ArgsT...>>
std::future< ResultT > invoke_task_with_priority (FunctionT &&function, uint16_t priority, ArgsT &&... args)
 Priority variant of invoke_task; requires a kPriorityType loop. More...
 

Protected Member Functions

virtual void on_begin ()
 Hook invoked once on the loop thread before the first task runs. More...
 
virtual void on_end ()
 Hook invoked once on the loop thread after the last task runs. More...
 
virtual void on_idle ()
 Hook invoked on the loop thread each time the queue becomes empty. More...
 
virtual void on_task_changed (Callback &&callback, uint32_t start_time)
 Dispatches a ready task on the loop thread. More...
 
virtual void on_task_timeout (Callback &&callback, uint32_t elapsed_time)
 Hook invoked when a task exceeds get_max_elapsed_time(). More...
 

Detailed Description

Serial task dispatcher with selectable queue backend and bounded timer registry.

Owns a thread that pulls tasks from a bounded queue and fires timer callbacks. Other threads may post via post_task, post_task_with_priority, invoke_task or exec_task from any context. The class is the building block of MultiLoop and the engine target of GraphTask::execute.

Member Typedef Documentation

◆ Callback

Callback type for tasks and event handlers.

Move-only so move-only targets such as std::packaged_task or lambdas holding std::unique_ptr can be posted directly without a shared trampoline.

Member Enumeration Documentation

◆ Priority

Built-in priority levels for kPriorityType loops; higher values dispatch first.

Enumerator
kNoPriority 

FIFO sentinel.

kLowestPriority 

Lowest real priority.

kTimerPriority 

Reserved for timer callbacks.

kNormalPriority 

Default user-task priority.

kHighestPriority 

Highest priority.

◆ Strategy

Back-pressure strategy applied when the bounded queue is at capacity.

Idle dispatch is unconditionally cv-driven; this enum only affects the push side.

Enumerator
kOptimizationStrategy 

Retry up to ten times, then drop one eligible task and push.

kPopStrategy 

Drop one eligible task immediately and push.

kBlockStrategy 

Retry indefinitely until space appears.

◆ Type

enum vlink::MessageLoop::Type : uint8_t

Internal queue implementation type.

Enumerator
kNormalType 

Mutex-protected FIFO queue (default).

kLockfreeType 

Lock-free MPMC queue.

kPriorityType 

Priority-ordered queue with droppable / protected split.

Constructor & Destructor Documentation

◆ MessageLoop() [1/2]

vlink::MessageLoop::MessageLoop ( )

Constructs a loop with the default kNormalType queue.

◆ MessageLoop() [2/2]

vlink::MessageLoop::MessageLoop ( Type  type)
explicit

Constructs a loop with the given queue type.

Parameters
typeQueue implementation.

◆ ~MessageLoop()

virtual vlink::MessageLoop::~MessageLoop ( )
virtual

Destructor; requests quit and joins the dispatcher thread if needed.

Member Function Documentation

◆ async_run()

bool vlink::MessageLoop::async_run ( )

Starts the loop on a new background thread.

Returns
true when the thread was started; false when the loop is already running.

◆ exec_task() [1/2]

template<typename CallbackT , typename >
Schedule::Status vlink::MessageLoop::exec_task ( const Schedule::Config config,
CallbackT &&  callback 
)

Schedules a void-returning callable and returns a chainable Schedule::Status.

Schedule::Config carries the delay, priority and timeout fields. The returned status supports on_catch / on_schedule_timeout / on_execution_timeout chaining. Posting is deferred until the handle is committed (when the temporary handle is destroyed at the end of the fluent expression), so every continuation is registered before the task runs. A caller that stores the handle instead of consuming it inline must call Schedule::Status::dispatch() to post the task and learn whether it was accepted.

Template Parameters
CallbackTCallable returning void.
Parameters
configScheduling envelope.
callbackCallable to schedule.
Returns
Chainable status object.
Here is the call graph for this function:

◆ exec_task() [2/2]

template<typename CallbackT , typename >
Schedule::RetStatus vlink::MessageLoop::exec_task ( const Schedule::Config config,
CallbackT &&  callback 
)

Schedules a bool-returning callable and returns a chainable Schedule::RetStatus.

on_then fires when the callable returns true; on_else fires when it returns false. Posting is deferred until the handle is committed (destroyed at the end of the fluent expression), guaranteeing every continuation is registered first; a stored handle must call Schedule::Status::dispatch() to post it.

Template Parameters
CallbackTCallable returning bool.
Parameters
configScheduling envelope.
callbackCallable to schedule.
Returns
Chainable status object.
Here is the call graph for this function:

◆ get_alive_state()

std::shared_ptr<AliveState> vlink::MessageLoop::get_alive_state ( ) const

Returns the shared lifetime flag used by cross-thread bridges.

The returned AliveState outlives this loop. Adapters that need to post continuations back to this loop should lock mtx, re-check alive, and only call back while still holding the lock.

Returns
Shared handle; never null while the loop object is alive.

◆ get_max_elapsed_time()

virtual uint32_t vlink::MessageLoop::get_max_elapsed_time ( ) const
virtual

Returns the maximum allowed task execution time in milliseconds.

Tasks exceeding this duration trigger on_task_timeout. Zero disables the check.

Returns
Maximum execution time in milliseconds.

Reimplemented in vlink::ProxyServer, vlink::ProxyAPI, vlink::DiscoveryViewer, and vlink::DiscoveryReporter.

◆ get_max_task_count()

virtual size_t vlink::MessageLoop::get_max_task_count ( ) const
virtual

Returns the maximum queue depth.

Returns
kMaxTaskSize (10000) by default.

Reimplemented in vlink::ProxyServer, vlink::ProxyAPI, vlink::VDBWriter, vlink::VDBReader, vlink::VCAPWriter, vlink::VCAPReader, vlink::DiscoveryViewer, and vlink::DiscoveryReporter.

◆ get_max_timer_count()

virtual size_t vlink::MessageLoop::get_max_timer_count ( ) const
virtual

Returns the maximum number of timers that can be attached.

Returns
kMaxTimerSize (100) by default.

◆ get_name()

const std::string& vlink::MessageLoop::get_name ( ) const

Returns the loop name set via set_name.

Returns
Reference to the stored name.

◆ get_strategy()

Strategy vlink::MessageLoop::get_strategy ( ) const

Returns the active back-pressure strategy.

Returns
Current strategy.

◆ get_task_count()

size_t vlink::MessageLoop::get_task_count ( ) const

Returns the current pending task count.

Returns
Number of tasks waiting in the queue.

◆ get_type()

Type vlink::MessageLoop::get_type ( ) const

Returns the queue type this loop was constructed with.

Returns
Queue type.

◆ invoke_task()

template<class FunctionT , class... ArgsT, typename ResultT >
std::future< ResultT > vlink::MessageLoop::invoke_task ( FunctionT &&  function,
ArgsT &&...  args 
)
inline

Dispatches a callable to the loop thread and returns a std::future for the result.

Thread-safe. When posting fails the returned future becomes ready with std::future_error / broken_promise.

Warning
Do not call .get() on the future from the loop's own thread; doing so deadlocks.
Template Parameters
FunctionTCallable type.
ArgsTArgument types.
ResultTReturn type (deduced).
Parameters
functionCallable to dispatch.
argsArguments forwarded to function.
Returns
Future that becomes ready after the callable completes.
Here is the call graph for this function:

◆ invoke_task_with_priority()

template<class FunctionT , class... ArgsT, typename ResultT >
std::future< ResultT > vlink::MessageLoop::invoke_task_with_priority ( FunctionT &&  function,
uint16_t  priority,
ArgsT &&...  args 
)
inline

Priority variant of invoke_task; requires a kPriorityType loop.

Template Parameters
FunctionTCallable type.
ArgsTArgument types.
ResultTReturn type (deduced).
Parameters
functionCallable to dispatch.
priorityDispatch priority.
argsArguments forwarded to function.
Returns
Future that becomes ready after the callable completes.
Here is the call graph for this function:

◆ is_busy()

bool vlink::MessageLoop::is_busy ( ) const

Reports whether the loop is currently executing a task.

Returns
true while a callback is on the call stack inside the loop.

◆ is_in_same_thread()

virtual bool vlink::MessageLoop::is_in_same_thread ( ) const
virtual

Reports whether the calling thread is owned by this loop.

Detects callbacks that re-enter the loop synchronously. For MultiLoop this also covers worker threads of the underlying pool.

Returns
true when called from a thread belonging to this loop.

Reimplemented in vlink::MultiLoop.

◆ is_ready_to_quit()

bool vlink::MessageLoop::is_ready_to_quit ( ) const

Reports whether quit has been requested and the loop is winding down.

Returns
true once quit has been observed.

◆ is_running()

bool vlink::MessageLoop::is_running ( ) const

Reports whether the loop is currently running.

Returns
true between a successful start and the corresponding quit.

◆ on_begin()

virtual void vlink::MessageLoop::on_begin ( )
protectedvirtual

Hook invoked once on the loop thread before the first task runs.

Subclasses override to perform per-thread initialisation.

Reimplemented in vlink::ProxyServer, vlink::ProxyAPI, vlink::VDBWriter, vlink::VDBReader, vlink::VCAPWriter, vlink::VCAPReader, vlink::DiscoveryViewer, vlink::DiscoveryReporter, and vlink::MultiLoop.

◆ on_end()

virtual void vlink::MessageLoop::on_end ( )
protectedvirtual

Hook invoked once on the loop thread after the last task runs.

Subclasses override to perform per-thread cleanup.

Reimplemented in vlink::ProxyServer, vlink::ProxyAPI, vlink::VDBWriter, vlink::VDBReader, vlink::VCAPWriter, vlink::VCAPReader, vlink::DiscoveryViewer, vlink::DiscoveryReporter, and vlink::MultiLoop.

◆ on_idle()

virtual void vlink::MessageLoop::on_idle ( )
protectedvirtual

Hook invoked on the loop thread each time the queue becomes empty.

Subclasses override to perform idle bookkeeping.

◆ on_task_changed()

virtual void vlink::MessageLoop::on_task_changed ( Callback &&  callback,
uint32_t  start_time 
)
protectedvirtual

Dispatches a ready task on the loop thread.

The default implementation invokes callback inline. Subclasses such as MultiLoop override to redirect the call to a worker pool; overrides that do not forward must invoke callback themselves or the task is silently dropped.

Parameters
callbackTask to dispatch.
start_timeMillisecond steady_clock timestamp captured at enqueue time, or 0 when elapsed tracking is disabled.

Reimplemented in vlink::MultiLoop.

◆ on_task_timeout()

virtual void vlink::MessageLoop::on_task_timeout ( Callback &&  callback,
uint32_t  elapsed_time 
)
protectedvirtual

Hook invoked when a task exceeds get_max_elapsed_time().

Parameters
callbackTask that timed out.
elapsed_timeActual execution time in milliseconds.

◆ post_task()

bool vlink::MessageLoop::post_task ( Callback &&  callback)

Posts a task for execution on the loop thread.

Thread-safe. Returns false when the loop is quitting or the configured Strategy cannot make room for the new task.

Parameters
callbackTask to post.
Returns
true when the task was enqueued.
Here is the caller graph for this function:

◆ post_task_handle()

TaskHandle vlink::MessageLoop::post_task_handle ( Callback &&  callback,
const PostTaskOptions options = {} 
)

Tracked variant of post_task returning a TaskHandle.

Parameters
callbackTask to post.
optionsOptional overflow / drop / cancellation policy.
Returns
Handle bound to the posted task; valid even when posting was rejected.

◆ post_task_with_priority()

bool vlink::MessageLoop::post_task_with_priority ( Callback &&  callback,
uint16_t  priority 
)

Posts a task with an explicit priority on a kPriorityType loop.

Higher priority values dispatch first. Non-priority loops reject the call and return false.

Parameters
callbackTask to post.
priorityDispatch priority in [kLowestPriority, kHighestPriority].
Returns
true when the task was enqueued.
Here is the caller graph for this function:

◆ post_task_with_priority_handle()

TaskHandle vlink::MessageLoop::post_task_with_priority_handle ( Callback &&  callback,
uint16_t  priority,
const PostTaskOptions options = {} 
)

Tracked variant of post_task_with_priority returning a TaskHandle.

Parameters
callbackTask to post.
priorityDispatch priority.
optionsOptional overflow / drop / cancellation policy.
Returns
Handle bound to the posted task.

◆ quit()

bool vlink::MessageLoop::quit ( bool  force = false)

Requests the loop to exit.

With force == false the current batch finishes and the loop exits afterwards. With force == true the in-flight batch is also aborted. Tasks queued after the request are rejected. Returns false when quit had already been called (only meaningful when force is false).

Parameters
forceWhen true, also discards the in-flight batch. Default: false.
Returns
true when the quit signal was accepted.

◆ register_begin_handler()

void vlink::MessageLoop::register_begin_handler ( Callback &&  callback)

Registers a callback fired once at loop thread startup.

Must be registered before run / async_run; later calls are ignored.

Parameters
callbackStartup handler.

◆ register_end_handler()

void vlink::MessageLoop::register_end_handler ( Callback &&  callback)

Registers a callback fired once when the loop thread exits.

Must be registered before run / async_run; later calls are ignored.

Parameters
callbackShutdown handler.

◆ register_idle_handler()

void vlink::MessageLoop::register_idle_handler ( Callback &&  callback)

Registers a callback fired every time the queue becomes empty.

Must be registered before run / async_run; later calls are ignored.

Parameters
callbackIdle handler.

◆ reset_lockfree_capacity()

void vlink::MessageLoop::reset_lockfree_capacity ( )

Recreates the lock-free queue, clearing all queued tasks and counters.

Applies only to kLockfreeType loops; on other types the call is a no-op. Must be invoked while the loop is stopped; calls made while it is running are logged and skipped.

◆ run()

bool vlink::MessageLoop::run ( )

Runs the loop on the calling thread until quit is requested.

Returns
true after a normal exit; false when the loop is already running.

◆ set_name()

void vlink::MessageLoop::set_name ( const std::string &  name)

Sets a human-readable name visible to profiling tools.

Parameters
nameLoop name.

◆ set_strategy()

void vlink::MessageLoop::set_strategy ( Strategy  strategy)

Replaces the back-pressure strategy.

Parameters
strategyNew strategy; takes effect on the next full-queue push.

◆ spin()

bool vlink::MessageLoop::spin ( )

Alias of run blocking the calling thread.

Returns
Same return value as run.

◆ spin_once()

bool vlink::MessageLoop::spin_once ( bool  block = true)

Processes one batch of pending tasks and timers on the calling thread.

Parameters
blockWhen true (default) blocks if the queue is empty; when false returns immediately.
Returns
true after a normal processing cycle; false when quitting or the call came from a thread that does not own the loop and is unrelated to run / async_run.

◆ wait_for_idle()

virtual bool vlink::MessageLoop::wait_for_idle ( int  ms = Timer::kInfinite,
bool  check = true 
)
virtual

Waits until the loop has drained its queue and is not executing a task.

Parameters
msMaximum wait in milliseconds; Timer::kInfinite means no limit.
checkWhen true (default) rejects calls from the loop's own thread.
Returns
true when the idle condition was reached within ms.

Reimplemented in vlink::MultiLoop.

◆ wait_for_quit()

bool vlink::MessageLoop::wait_for_quit ( int  ms = Timer::kInfinite,
bool  check = true 
)

Waits until the loop has fully exited.

Parameters
msMaximum wait in milliseconds; Timer::kInfinite means no limit.
checkWhen true (default) rejects calls from the loop's own thread.
Returns
true if the loop exited before the timeout.

◆ wakeup()

bool vlink::MessageLoop::wakeup ( )

Wakes the loop thread if it is suspended in its idle wait.

Concurrent calls coalesce; only the first one after the previous wakeup actually signals.

Returns
true when a wakeup is pending (newly issued or already in flight).

The documentation for this class was generated from the following file: