executor
An executor provides mechanisms for scheduling work for execution.
Requires: C++20
Synopsis
Defined in header <boost/capy/executor.hpp>
namespace boost::capy {
template<class E>
concept executor =
std::copy_constructible<E> &&
std::equality_comparable<E> &&
requires(E& e, E const& ce, std::coroutine_handle<> h) {
{ ce.context() } -> std::same_as<decltype(ce.context())&>;
{ ce.on_work_started() } noexcept;
{ ce.on_work_finished() } noexcept;
{ ce.dispatch(h) } -> std::convertible_to<std::coroutine_handle<>>;
{ ce.post(h) };
{ ce.defer(h) };
};
} // namespace boost::capy
Description
A type meeting the executor requirements embodies a set of rules for determining how submitted coroutines are to be executed. An executor is a lightweight, copyable handle to an execution context such as a thread pool, I/O context, or strand.
The executor provides three scheduling operations:
-
dispatch — Run inline if allowed, else queue. Cheapest path.
-
post — Always queue, never inline. Guaranteed asynchrony.
-
defer — Always queue with continuation hint. Enables optimizations.
No-Throw Guarantee
The following operations shall not exit via an exception:
-
Constructors
-
Comparison operators
-
Copy/move operations
-
swap -
context() -
on_work_started() -
on_work_finished()
Thread Safety
The executor copy constructor, comparison operators, and other member functions shall not introduce data races as a result of concurrent calls from different threads.
Executor Validity
Let ctx be the execution context returned by context(). An executor
becomes invalid when the first call to ctx.shutdown() returns. The effect
of calling dispatch, post, or defer on an invalid executor is undefined.
The copy constructor, comparison operators, and context() remain valid
until ctx is destroyed.
Valid Expressions
Given:
-
e— a value of typeE -
ce— a const value of typeE -
h— a value of typestd::coroutine_handle<>
| Expression | Return Type | Description |
|---|---|---|
|
|
Return a reference to the associated execution context |
|
— |
Inform the executor that work is beginning (must not throw) |
|
— |
Inform the executor that work has completed (must not throw) |
|
convertible to |
Execute inline if permitted, otherwise queue |
|
— |
Queue for later execution, never inline |
|
— |
Queue with continuation hint for optimization |
Example
#include <boost/capy/executor.hpp>
using boost::capy::executor;
class my_executor
{
my_context* ctx_;
public:
my_executor(my_context& ctx) : ctx_(&ctx) {}
my_context& context() const noexcept { return *ctx_; }
void on_work_started() const noexcept { ctx_->work_++; }
void on_work_finished() const noexcept { ctx_->work_--; }
std::coroutine_handle<> dispatch(std::coroutine_handle<> h) const
{
if (ctx_->running_in_this_thread())
return h; // Inline execution
post(h);
return std::noop_coroutine();
}
void post(std::coroutine_handle<> h) const
{
ctx_->queue_.push(h);
}
void defer(std::coroutine_handle<> h) const
{
ctx_->local_queue_.push(h); // Thread-local optimization
}
bool operator==(my_executor const& other) const noexcept
{
return ctx_ == other.ctx_;
}
};
static_assert(executor<my_executor>);
See Also
-
is_execution_context — Execution context concept
-
dispatcher — Simpler scheduling interface
-
Executors — Tutorial on the execution model