У нас есть общий ресурс: пул памяти, потокобезопасный API, выбирайте сами. Мы хотели бы контролировать доступ к указанному ресурсу через цепь ASIO. Все процедуры, обращающиеся к ресурсу, должны выполняться на этом канале.
Мы также используем сопрограммы C++20 и наслаждаемся иллюзией последовательного выполнения, которую они обеспечивают.
При доступе к общему ресурсу мы хотели бы приостановить сопрограмму с помощью co_await, переключиться на благословенную цепочку, сделать что-нибудь с ресурсом, а затем вернуться обратно к сопрограмме на ее родном исполнителе.
Предупреждения:
- Мы не хотим использовать "трюк", потому что эргономика плохая, и это состояние гонки, ожидающее своего часа, т.е.
Код: Выделить всё
dispatch
Код: Выделить всё
auto s1 = bind_executor(strand, asio::deferred);
co_await asio::dispatch(s1);
// Access shared resource
co_await asio::dispatch(asio::deferred);
- Мы не хотим помещать указанный трюк в другой asio::awaitable и, возможно, выделять кадр сопрограммы для операций, которые не запрашивают для одного (через use_awaitable)
Это то, что я взломал утро, очевидно, это не очень хорошо (не используются концепции, не пересылаются аргументы, не разрешены возвращаемые значения и т. д.), но это иллюстрирует то, к чему я стремлюсь:
(Godbolt)< /p>
Код: Выделить всё
static std::atomic_int tid_gen;
thread_local int const tid = tid_gen++;
inline void out(auto const& msg) { std::print("T{:x} {}\n", tid, msg); }
template
auto async_run_on(F f, Ex ex, CT&& token) {
return asio::async_initiate(
[](auto handler, F f, Ex ex) {
ex.dispatch(
[=, handler = std::move(handler)]() mutable {
std::invoke(f);
handler.get_executor().execute(std::move(handler));
},
asio::get_associated_allocator(ex));
},
token, std::move(f), ex);
}
asio::awaitable f(auto strand) {
out("Main");
co_await async_run_on([](){ out("Strand"); }, strand, asio::deferred);
out("Main again");
}
int main() {
asio::io_context io;
asio::thread_pool tp(1);
co_spawn(io, f(make_strand(tp)), asio::detached);
io.run();
}
Вопрос
Как предполагается этот вариант использования?
У меня очень плохо получается ASIO, худший. Также нет никаких шансов, что я первый столкнусь с этой проблемой. Это заставляет меня с огромным подозрением относиться к любому решению, которое я придумываю. Сопрограммы и нити — это строительные блоки ASIO, и я не sehe или ChrisK, я не тот человек, который выясняет, как эти кусочки головоломки сочетаются друг с другом.
Но Google, SO и ASIO все документы странно молчат об этом. Между примерами, приведенными для цепочек, и примерами, приведенными для сопрограмм, очень мало перекрестного взаимодействия.
Должны ли мы каждый раз выполнять co_await''' отложенные операции, связанные с цепочкой? или есть бесплатная функция, которую я где-то совсем пропустил?
Подробнее здесь: https://stackoverflow.com/questions/784 ... n-a-strand
Мобильная версия