ASIO: co_await, вызываемый для запуска на цепочкеC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 ASIO: co_await, вызываемый для запуска на цепочке

Сообщение Anonymous »

Проблема
У нас есть общий ресурс: пул памяти, потокобезопасный 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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»