std::execution::scheduler
Определён в заголовочном файле <execution> | ||
|---|---|---|
template< class Sch >
concept scheduler =
std::derived_from<
typename std::remove_cvref_t<Sch>::scheduler_concept,
scheduler_tag> &&
/*queryable*/<Sch> &&
requires(Sch&& sch)
{
{
std::execution::schedule(std::forward<Sch>(sch))
} -> std::execution::sender;
{
std::execution::get_forward_progress_guarantee(sch)
} -> std::same_as<std::execution::forward_progress_guarantee>;
} &&
std::equality_comparable<std::remove_cvref_t<Sch>> &&
std::copy_constructible<std::remove_cvref_t<Sch>>;
};
| (1) | (начиная с C++26) |
| Вспомогательный тип-тег | ||
struct scheduler_tag {};
| (2) | (начиная с C++26) |
Концепт scheduler моделируется типами, которые являются планировщиками, то есть облегченными обработчиками ресурсов выполнения, таких как пулы потоков, совместимые с библиотекой выполнения C++.
Семантические требования
Для планировщика типа Sch и среды выполнения типа Env, таких что выполняется sender_in<schedule_result_t<Sch>, Env>, моделируется /*sender-in-of*/<schedule_result_t<Sch>, Env>.
Конструктор копирования, деструктор, оператор сравнения на равенство и функции-члены swap планировщика не должны выбрасывать исключения.
Все эти функции-члены, а также функция schedule типа планировщика должны быть потокобезопасными.
Два планировщика равны только в том случае, если они представляют один и тот же ресурс выполнения.
Для заданного планировщика sch выражение get_completion_scheduler<set_value_t>(get_env(schedule(sch))) сравнивается на равенство с sch.
Для заданного планировщика sch, типа T (который является одним из void, set_value_t, set_error_t или set_stopped_t) и набора подвыражений envs, если выражение get_completion_domain<T>(sch, envs...) корректно, то выражение get_completion_domain<T>(get_env(schedule(sch)), envs...) также корректно и имеет тот же тип.
Деструктор планировщика не должен блокироваться в ожидании завершения каких-либо получателей, подключённых к объектам отправителя, возвращённым функцией 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
См. также
|
(C++26) | подготавливает граф задач для выполнения с помощью заданного планировщика (объект точки настройки) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/execution/scheduler