VLink  2.0.0
A high-performance communication middleware
message_loop.h File Reference

Single-threaded task dispatcher with three queue backends, timers and scheduling envelopes. More...

#include <atomic>
#include <functional>
#include <future>
#include <limits>
#include <memory>
#include <mutex>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include "./functional.h"
#include "./memory_resource.h"
#include "./schedule.h"
#include "./task_handle.h"
#include "./timer.h"
Include dependency graph for message_loop.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  vlink::MessageLoop
 Serial task dispatcher with selectable queue backend and bounded timer registry. More...
 
struct  vlink::MessageLoop::AliveState
 Lifetime gate shared with cross-thread observers. More...
 

Namespaces

 

Detailed Description

Single-threaded task dispatcher with three queue backends, timers and scheduling envelopes.

MessageLoop is VLink's serial task executor. It owns a bounded task queue and the timer registry attached to it; tasks posted from any thread execute in order on the loop's own thread. Three queue implementations are available; the choice is fixed at construction.

Dispatch mode table
Queue type Backend Capacity Properties
kNormalType mutex + std::deque (or pmr) 10000 FIFO, lock-based (default)
kLockfreeType MpmcQueue<Callback> 10000 Lock-free MPMC
kPriorityType Two pmr priority queues 10000 Droppable / protected split

Back-pressure on a full queue is selected by Strategy: kOptimizationStrategy retries up to ten times with 1 ms sleeps before dropping an eligible task, kPopStrategy drops immediately, kBlockStrategy retries indefinitely. Idle dispatch is always condition-variable driven and independent of Strategy.

Lifecycle diagram
*                          run() / async_run()
*   +--------+                        |
*   |  idle  | ----- async_run -----> | spawn thread
*   +--------+                        |
*      ^                              v
*      |                          +--------+
*      |   wait_for_quit          | active |  <-- post_task / exec_task
*      |       (joined)           +--------+
*      |                              |
*      |                       quit() | quit(true)
*      |                              v
*      |                          +--------+
*      +------- on_end() -------- | drain  | -- pending tasks --> dropped
*                                 +--------+
* 
Priority levels
Symbol Value Notes
kNoPriority 0 FIFO sentinel
kLowestPriority 1 Lowest real priority
kTimerPriority 50 Reserved for timer callbacks
kNormalPriority 100 Default user-task priority
kHighestPriority 65535 Highest priority
Example
loop.async_run();
loop.post_task([] { do_work(); });
auto fut = loop.invoke_task([]() -> int { return compute(); });
int result = fut.get(); // wait from a different thread
loop.quit();
Note
Maximum queue depth is 10000 (kMaxTaskSize) and maximum timer count is 100 (kMaxTimerSize). Blocking .get() on the future returned by invoke_task from inside the loop thread deadlocks; always call it from another thread.