std::execution:: scheduler

From cppreference.com
Defined in header <execution>
template < class Sch >

concept scheduler =
std:: derived_from <
typename std:: remove_cvref_t < Sch > :: scheduler_concept ,
scheduler_t > &&
/*queryable*/ < Sch > &&
requires ( Sch && sch )
{
{
std :: execution :: schedule ( std:: forward < Sch > ( sch ) )
} - > std :: execution :: sender ;
{
auto (
std :: execution :: get_completion_scheduler <
std :: execution :: set_value_t > (
std :: execution :: get_env (
std :: execution :: schedule (
std:: forward < Sch > ( sch ) ) ) ) )
} - > std:: same_as < std:: remove_cvref_t < Sch >> ;
} &&
std:: equality_comparable < std:: remove_cvref_t < Sch >> &&
std:: copy_constructible < std:: remove_cvref_t < Sch >> ;

} ;
(1) (since C++26)
Helper tag type
struct scheduler_t { } ;
(2) (since C++26)

The concept scheduler is modeled by types that are schedulers , that is, lightweight handlers to execution resources such as thread pools that work with the C++ execution library.

Semantic requirements

Given a scheduler of type Sch and execution environment of type Env such that sender_in < schedule_result_t < Sch > , Env > is satisfied, then /*sender-in-of*/ < schedule_result_t < Sch > , Env > is modeled.

The scheduler's copy constructor, destructor, equality comparison, or swap member functions must be non-throwing.

All of those member functions as well as the scheduler type's schedule function must be thread-safe.

Two schedulers are equal only if they represent the same execution resource.

For a given scheduler sch , the expression get_completion_scheduler < set_value_t > ( get_env ( schedule ( sch ) ) ) compares equal to sch .

For a given scheduler sch , if the expression get_domain ( sch ) is well-formed, then the expression get_domain ( get_env ( schedule ( sch ) ) ) is also well-formed and has the same type.

The destructor of a scheduler must not block pending completion of any receivers connected to the sender objects returned from schedule (the underlying resource may provide a separate API to wait for completion of submitted function objects)

Examples

simple wrapper for std::execution::run_loop that constantly polls run_loop's queue on a single dedicated thread. Demo using draft reference implementation: https://godbolt.org/z/146fY4Y91

#include <execution>
#include <iostream>
#include <thread>
 
class single_thread_context
{
    std::execution::run_loop loop_{};
    std::jthread thread_;
 
public:
    single_thread_context()
        : thread_([this] { loop_.run(); })
    {}
    single_thread_context(single_thread_context&&) = delete;
 
    ~single_thread_context()
    {
        loop_.finish();
    }
 
    std::execution::scheduler auto get_scheduler() noexcept
    {
        return loop_.get_scheduler();
    }
};
 
int main()
{
    single_thread_context ctx;
 
    std::execution::sender auto snd =
        std::execution::schedule(ctx.get_scheduler())
        | std::execution::then([]
            {
                std::cout << "Hello world! Have an int.\n";
                return 015;
            })
        | std::execution::then([](int arg) { return arg + 42; });
 
    auto [i] = std::this_thread::sync_wait(snd).value();
 
    std::cout << "Back in the main thread, result is " << i << '\n';
}

Output:

Hello world! Have an int.
Back in the main thread, result is 55

See also

prepares a task graph for execution on a given scheduler
(customization point object)