我可以使用stackful协程作为steady_timer的等待处理程序吗?steady_imer是在非常stackfu

Can I use a stackful coroutine as the wait handler of a steady_timer which is defined inside the very stackful coroutine?

本文关键字:steady 程序 imer stackfu 非常 处理 stackful 可以使 程作 我可以 timer      更新时间:2023-10-16

我可以按以下方式使用stackful协程和boost::asio::steady_timer::async_wait吗?关键是(我的理解是,不确定)在等待期间,局部变量timer不在堆栈上,因此无法访问。那么回调能正常进行吗?(仅供参考,它在我的Mac上使用clang++5.0运行良好。)

boost::asio::io_service io;
void Work(boost::asio::yield_context yield) {
boost::asio::steady_timer timer(io);
timer.expires_from_now(std::chrono::seconds(5));
timer.async_wait(yield);
cout << "Woke up." << endl;
}
int main() {
boost::asio::spawn(io, Work);
io.run();
return 0;
}

我认为值得对这个问题进行比较:提高asio deadline_timer

是的,将boost::asio::yield_context传递给在同一协程中具有自动存储持续时间的对象是安全的。

Boost.Coroutine使用Boost.Context来执行上下文切换。Boost.Context提供了一种方法来挂起当前执行路径,保留堆栈(包括局部变量,如Work()timer),并传输执行控制,允许同一线程使用不同的堆栈运行。因此,对于具有自动存储持续时间的boost::asio::steady_timer对象,其寿命将在以下情况之一时结束:

  • 控件通过return退出由Work()指定的块,到达函数末尾,或者异常展开堆栈
  • 关联的io_service被销毁。内部处理程序维护协程的共享所有权,当io_service被销毁时,所有关联的处理程序也被销毁。这种破坏将导致Boost.Coroutine强制每个协同程序的堆栈展开

当调用boost::asio::spawn()时,Boost.Asio执行一些设置工作,然后将dispatch()一个内部处理程序,该处理程序将使用用户提供的函数作为入口点创建协同程序。当yield_context对象作为处理程序传递给异步操作时,Boost.Asio将在使用完成处理程序启动异步操作后立即产生,该完成处理程序将复制结果并恢复协程。协程拥有的strand用于保证收益发生在恢复之前。以下是示例代码的执行示例:

boost::asio::io_service io_service;
boost::asio::spawn(io_service, &Work);
`-- dispatch a coroutine creator
into the io_service.
io_service.run();
|-- invoke the coroutine creator
|   handler.
|   |-- create and jump into
|   |   into coroutine         ----> Work()
:   :                                |-- timer created
:   :                                |-- setting timer expiration
:   :                                |-- timer.async_wait(yield)
:   :                                |   |-- create error_code on stack
:   :                                |   |-- initiate async_wait operation,
:   :                                |   |   passing in completion handler that
:   :                                |   |   will resume the coroutine
|   `-- return                 <---- |   |-- yield
|-- io_service has work (the         :   :
|   async_wait operation)            :   :
|   ...async wait completes...       :   :
|-- invoke completion handler        :   :
|   |-- copies error_code            :   :
|   |   provided by service          :   :
|   |   into the one on the          :   :
|   |   coroutine stack              :   :
|   |-- resume                 ----> |   `-- return error code
:   :                                |-- cout << "Waked up." << endl;
:   :                                |-- exiting Work() block, timer is 
:   :                                |   destroyed.
|   `-- return                 <---- `-- coroutine done, yielding
`-- no outstanding work in 
io_service, return.

是的,它应该可以工作。boost::asio::steady_timer(io)在io服务上注册计时器。