我可以使用堆栈协程作为在非常堆栈的协程中定义的steady_timer的等待处理程序吗?

时间:2014-02-14 05:39:40

标签: c++ boost boost-asio

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

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;
}

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

2 个答案:

答案 0 :(得分:8)

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

Boost.Coroutine使用Boost.Context执行上下文切换。 Boost.Context提供了一种暂停当前执行路径,保留堆栈(包括Work()的{​​{1}}等局部变量)和传输执行控制的方法,允许相同的线程以不同的方式运行堆。因此,如果timer对象具有自动存储持续时间,则其寿命将在以下任一时间结束:

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

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

yield_context

答案 1 :(得分:2)

是的 - 它应该有效。 boost :: asio :: steady_timer timer(io)在io-service上注册定时器。