std::execution::run_loop
Определён в заголовочном файле <execution> | ||
|---|---|---|
class run_loop
{
public:
run_loop() noexcept;
run_loop(run_loop&&) = delete;
~run_loop();
/*run-loop-scheduler*/ get_scheduler() noexcept;
void run() noexcept;
void finish() noexcept;
};
| (начиная с C++26) |
run_loop — это лёгкий ресурс выполнения, владеющий потокобезопасной очередью работ с порядком FIFO, который можно использовать как цикл событий с ручным управлением. Планировщик, полученный из run_loop, ставит работы в эту очередь, а run выполняет работы из очереди в вызывающем потоке.
Этот тип в первую очередь полезен для тестов, примеров и простого выполнения в стиле цикла событий. Сам по себе он не создаёт поток: программа определяет, какой поток вызывает run.
Функции-члены
создаёт run_loop (открытая функция-член) |
|
уничтожает run_loop (открытая функция-член) |
|
получает планировщик, связанный с run_loop (открытая функция-член) |
|
| выполняет работы из очереди в вызывающем потоке (открытая функция-член) |
|
запрашивает завершение run_loop (открытая функция-член) |
Связанный планировщик
get_scheduler возвращает объект неуказанного типа, обозначенный здесь как /*run-loop-scheduler*/.
Планировщики, полученные из одного и того же run_loop, сравниваются как равные. Планировщики, полученные из разных объектов run_loop, сравниваются как неравные. Планировщик, полученный из run_loop, остаётся действительным только пока существует соответствующий объект run_loop.
Вызов schedule для планировщика run_loop возвращает отправителя. Отправитель завершается с set_value() после выполнения запланированной работы. Если токен остановки получателя допускает остановку, отправитель вместо этого может завершиться с set_stopped(), если остановка была запрошена до выполнения операции.
Выполнение
run_loop поддерживает внутреннее состояние (которым может быть starting, running, finishing или finished) и счётчик состояний операций, находящихся в очереди.
run можно вызвать, если цикл ещё не запущен или для него запрошено завершение. Если цикл ещё не запущен, run переводит его в состояние выполнения. Затем он снова и снова извлекает первое состояние операции из очереди и выполняет его. Если работы нет, run блокируется, пока в очередь не будет добавлена работа или цикл не будет готов к завершению. run возвращается после запроса finish и выполнения всех работ из очереди.
finish запрашивает завершение цикла. Его можно вызвать до или во время run; он пробуждает заблокированный вызов run, чтобы тот мог вернуться после опустошения очереди.
Уничтожение run_loop во время его выполнения или при наличии состояний операций в очереди вызывает std::terminate.
Примечания
Запуск состояния операции, созданного с помощью планировщика run_loop, помещает операцию в очередь. Получатель операции завершается позднее, когда поток, выполняющий run, извлекает эту операцию из очереди.
За исключением конкурентных вызовов самого run и уничтожения объекта, операции с run_loop не приводят к гонкам данных.
Пример
run_loop можно использовать как основу для простого однопоточного контекста выполнения.
#include <execution>
#include <iostream>
#include <thread>
class single_thread_context
{
std::execution::run_loop loop_;
std::jthread worker_;
public:
single_thread_context()
: worker_([this] { loop_.run(); })
{}
~single_thread_context()
{
loop_.finish();
}
auto get_scheduler() noexcept
{
return loop_.get_scheduler();
}
};
int main()
{
namespace ex = std::execution;
single_thread_context ctx;
auto snd =
ex::schedule(ctx.get_scheduler())
| ex::then([] {
std::cout << "work runs on the loop\n";
return 42;
});
auto [value] = std::this_thread::sync_wait(std::move(snd)).value();
std::cout << value << '\n';
}
Вывод:
work runs on the loop 42
См. также
|
(C++26) | задаёт требования, согласно которым тип является планировщиком (концепт) |
|
(C++26) | подготавливает граф задач для выполнения с помощью заданного планировщика (объект-точка настройки) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/execution/run_loop