【问题标题】:asio custom async function and c++20 coroutinesasio 自定义异步函数和 c++20 协程
【发布时间】:2021-12-27 02:18:06
【问题描述】:

我正在将我的 asio 应用程序从它的堆栈协程迁移到 c++20 无堆栈协程。我有一个现有的类方法,如下所示:

int my_async_op(asio::yield_context yield) {
    using tResult = asio::async_result<asio::yield_context, void(boost::system::error_code, int)>;
    tResult::completion_handler_type handler(yield);
    tResult result(handler);
    ...
    boost::system::error_code ec;
    asio::some_async_op(yield[ec]);
    ...
    handler(boost::system::error_code(), 42);
    return result.get();
}

...并且是这样调用的:

boost::system::error_code ec;
x = my_async_op(yield[ec]);

当迁移到 C++20 无堆栈协程时,需要链接,我的函数骨架现在看起来像这样:

asio::awaitable<int> my_async_op(...) {
    ...
    boost::system::error_code ec;
    co_await asio::some_async_op(net::redirect_error(net::use_awaitable, ec));
    ...
    co_return 42;
}

...但是这样称呼:

boost::system::error_code ec;
x = co_await my_async_op(net::redirect_error(net::use_awaitable, ec));

因此骨架需要更新以获取完成令牌,与本机 asio 异步操作相同,但我可以找到一个参考示例来解决,我承认发现 asio 源代码难以解析。

任何指导或参考将不胜感激。

编辑:我想我已经接近 http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/p1943r0.html 的 asio::async_initiate。我的函数现在看起来像这样:

template<typename T>
auto my_async_op<T&& token) {
    return asio::async_initiate<T, void(boost::system::error_code, int)>(
        [&](auto handler)->void {
            ...
            boost::system::error_code ec;
            co_await asio::some_async_op(asio::redirect_error(asio::use_awaitable, ec));
            ...
            handler(boost::system::error_code(), 42);
        },
        token
    );
}

唯一的问题是我在嵌套的 co_await 调用中遇到编译器错误:

XXX.h:97:12: error: unable to find the promise type for this coroutine
   97 | co_await asio::some_async_op(net::redirect_error(net::use_awaitable, ec));

会继续磨合。

编辑:现在正在调查...https://github.com/chriskohlhoff/asio/issues/795

【问题讨论】:

    标签: c++ c++20 coroutine asio


    【解决方案1】:

    如果您的要求是编写自己的 async_xyz 函数,您可以使用 async_initiate。您应该使用另一个线程来运行该函数。

    我这样做是为了计算提升线程池上的哈希值。

    例如:

    template <boost::asio::completion_token_for<void (std::string)> CompletionToken>
    auto
    async_hash (boost::asio::thread_pool &pool, boost::asio::io_context &io_context, std::string const &password, CompletionToken &&token)
    {
      return boost::asio::async_initiate<CompletionToken, void (std::string)> (
          [&] (auto completion_handler, std::string const &passwordToHash) {
            auto io_eq = boost::asio::prefer (io_context.get_executor (), boost::asio::execution::outstanding_work.tracked);
            boost::asio::post (pool, [&, io_eq = std::move (io_eq), completion_handler = std::move (completion_handler), passwordToHash] () mutable {
              auto hashedPw = pw_to_hash (passwordToHash);
              boost::asio::post (io_eq, [hashedPw = std::move (hashedPw), completion_handler = std::move (completion_handler)] () mutable { completion_handler (hashedPw); });
            });
          },
          token, password);
    }
    

    在调用端,您可以像协程中的其他 async_xyz 函数一样调用它:

    auto hashedPw = co_await async_hash (pool, io_context, createAccountObject.password, boost::asio::use_awaitable);
    

    【讨论】:

      猜你喜欢
      • 2021-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-29
      • 2021-09-03
      • 2021-11-15
      • 1970-01-01
      相关资源
      最近更新 更多