В документации boost::asio::this_coro::executor указано, что это
Ожидаемый объект, возвращающий исполнителя текущей сопрограммы.
Мне это кажется несколько расплывчатым, когда в игру вступают несколько Executors; Я предполагал, что co_await это обеспечит Executor, в котором в данный момент выполняется сопрограмма, т. е. я ожидал, что утверждение в этом фрагменте будет успешным:
boost::asio::io_context ioc;
auto io_ex = ioc.get_executor();
boost::asio::co_spawn(io_ex,
[&]() -> boost::asio::awaitable<void> {
auto switch_strand = boost::asio::make_strand(io_ex);
co_await boost::asio::post(switch_strand, boost::asio::use_awaitable);
assert(switch_strand == co_await boost::asio::this_coro::executor);
},
boost::asio::detached);
ioc.run();
Однако оказывается, что даже после перехода от post к switch_strand, io_ex == co_await boost::asio::this_coro::executor. Почему это происходит? Будет ли co_await boost::asio::this_coro::executor всегда создавать Executor сопрограмму, которая изначально была co_spawn включена, независимо от того, переключусь ли я на любую другую Executor внутри сопрограммы? Вызов post с switch_strand вообще «переключается на любую другую Executor внутри сопрограммы»?





Исполнитель является свойством сопрограммы. Вот почему вы можете запросить тип обещания awaitable, используя трансформируемый объект (this_coro::executor). Возможно, даже был сделан сознательный выбор дизайна, который выбрал
auto ex = co_await this_coro::executor; // this syntax
над
auto ex = co_await this_coro::executor(); // instead of this syntax
в отличие от других интерактивных преобразований.
Почему это происходит?
Так оно и было задумано. В большинстве случаев сопрограммы являются самоизменяющимися продолжениями. Продолжения являются обработчиками. Обработчики могут иметь связанных исполнителей. Когда вы co_spawn(ex, foo, ...) просите все эти продолжения привязать к ex.
См. также комментарии к коду
Будет ли co_await boost::asio::this_coro::executor всегда создавать Исполнителя, на котором изначально была создана сопрограмма
Да. См. также преобразование в коде
независимо от того, переключаюсь ли я на любого другого исполнителя внутри сопрограммы? Призыв к публикации с помощью switch_strand даже «переключается на любого другого исполнителя в сопрограмме»?
Да и нет:
co_await post(bind_executor(x, deferred)); приведет к возобновлению работы сопрограммы при x.Да, я тоже это понимаю.
Кстати. Я просто хочу отметить, что я уже знал оба места исходного кода, на которые вы ссылались, но все еще не мог самостоятельно ответить на свои вопросы. В частности, несмотря на то, что я просмотрел реализацию awaitable_frame_base::await_transform(this_coro::executor_t), я не смог сам подтвердить, что ее результат определенно был результатом, переданным исполнителем co_spawn. Хотя обычно я справляюсь с документацией и исходным кодом, сложность (и, возможно, запутывание) в Boost.Asio — это нечто иное.
Спасибо, это прояснило ситуацию. Итак, насколько я понимаю ваш ответ, до тех пор, пока я явно не укажу
bind_executorнаboost::asio::use_awaitable(илиboost::asio::deferred),co_awaitон возобновит выполнение сопрограмм («оригинальных») исполнителя, переданныхco_spawn(он жеco_await boost::asio::this_coro::executor), даже если он в данный момент выполняется на каком-то другом (явно связанном) исполнителе. Можете ли вы это подтвердить?