c++ 协程:如何从非协程感知库代码调用async_* 函数

nr9pn0ug  于 2023-03-14  发布在  其他
关注(0)|答案(1)|浏览(99)

我正尝试在一个项目中使用asio协程,这个项目使用一个内部库来实现核心功能。
低级例程是在库所使用的抽象接口的具体实现中实现的。具体实现所保存的数据通常足以调用低级函数。

#include <boost/asio/io_context.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/deadline_timer.hpp>

struct RequestContext
{
    virtual void doSomething() = 0;
};

struct AsyncRequestContext : public RequestContext
{
    boost::asio::io_context ioc;

    void doSomething() override
    {
        // Do something asynchronous with coroutines ...
        boost::asio::deadline_timer timer(ioc);
        timer.expires_from_now(boost::posix_time::seconds(5));

        // Howto do an async call with cocoutines here?
        //co_await timer.async_wait(boost::asio::use_awaitable);

        timer.wait();
    }
};

// This is in a library which does not know about coroutines
void middle(RequestContext& rctx)
{
    rctx.doSomething();
}

int main()
{
    AsyncRequestContext rctx;

    // Spawn a listening port
    boost::asio::co_spawn(
        rctx.ioc,
        [&rctx]() -> boost::asio::awaitable<void> {

            // Call library code 
            middle(rctx);

            co_return;
        },
        boost::asio::detached);

    rctx.ioc.run();

    return 0;
}

我的问题是,协程spawn在调用层次结构的顶部,然后调用库代码,库代码调用调用树中的低级例程。
我不知道如何在不改变接口的情况下使用co_await和这些较低层函数中的async_*函数。

e5nqia27

e5nqia271#

协程是一种灵活的工具,但是它们的工作方式、调度和恢复方式最终取决于您正在使用的特定接口和系统。
协程的全部意义在于它们是函数的实现细节,这意味着你不知道某个函数是协程;你所知道的就是它是一个接受一些参数并返回一个值的函数,一个异步函数会返回某种“future-value”类型,它代表一个将要生成但不一定可用的值。
协程只是编写这样一个函数的一种方法。
因此,与异步函数交互的方式在概念上与函数是作为协程实现还是其他方式实现是正交的,也就是说,你与“未来值”对话。
因此,如果你在一个地方有异步生成值的代码,而在另一个地方有需要与之同步并接收该值的代码......你需要从第一个地方到第二个地方获取返回值。
这通常是通过让它们之间的函数返回那个值来完成的。但是你怎么做取决于你。你可以使用某种类型的成员变量,全局变量,或者其他东西。你的AsyncRequestContext可以存储timer.await的结果,例如。当然,这意味着它不是一个协程,是的,它不是一个异步函数。因为它没有被写成这样。
它需要 start 一个异步进程,并存储future-value,但是doRequest本身不是一个协程或异步函数,如果它需要在其中做协程的东西,使用一个本身就是协程的lambda。

相关问题