Namespaces
Variants

std::execution:: scheduler

From cppreference.net
Определено в заголовочном файле <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) (начиная с C++26)
Вспомогательный тип-метка
struct scheduler_t { } ;
(2) (начиная с C++26)

Концепция scheduler моделируется типами, которые являются планировщиками , то есть легковесными обработчиками ресурсов выполнения, таких как пулы потоков, которые работают с библиотекой выполнения C++.

Семантические требования

Для планировщика типа Sch и среды выполнения типа Env таких, что выполняется условие sender_in < schedule_result_t < Sch > , Env > , тогда /*sender-in-of*/ < schedule_result_t < Sch > , Env > моделируется.

Конструктор копирования, деструктор, оператор сравнения на равенство или функции-члены обмена планировщика должны быть не генерирующими исключения.

Все эти функции-члены, а также функция schedule типа планировщика должны быть потокобезопасными.

Два планировщика равны только в том случае, если они представляют один и тот же ресурс выполнения.

Для заданного планировщика sch выражение get_completion_scheduler < set_value_t > ( get_env ( schedule ( sch ) ) ) сравнивается эквивалентно с sch .

Для заданного планировщика sch , если выражение get_domain ( sch ) корректно сформировано, то выражение get_domain ( get_env ( schedule ( sch ) ) ) также корректно сформировано и имеет тот же тип.

Деструктор планировщика не должен блокировать выполнение до завершения любых получателей, подключенных к объектам-отправителям, возвращаемым из schedule (базовый ресурс может предоставлять отдельный API для ожидания завершения отправленных функциональных объектов)

Примеры

простой враппер для std::execution::run_loop , который постоянно опрашивает очередь run_loop в отдельном выделенном потоке. Демонстрация с использованием черновой эталонной реализации: 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';
}

Вывод:

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

Смотрите также

подготавливает граф задач для выполнения на заданном планировщике
(объект точки кастомизации)