c++ - 在 asio stackful 协程中直接使用 spawn 是否安全?

标签 c++ boost boost-asio coroutine

当我使用 spawn 在协程中启动一个新的 stackfull 协程时,valgrind 说很多使用未初始化的值( valgrind output )。

然后我使用 io_service.post 调用处理程序,并在其中启动一个新的 stackfull 协程,一切似乎都很好。

我搜索并阅读了一些文档,但找不到有关如何在 stackfull 协程中安全地创建新的 stackfull 协程的信息。

代码如下:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/system_timer.hpp>
#include <chrono>

using namespace std;

int main()
{
    auto use_post = false;
    boost::asio::io_service io_service;
    boost::asio::spawn(io_service,
                       [&io_service, &use_post](boost::asio::yield_context yield){
        if(use_post){
            io_service.post([&io_service]{
                boost::asio::spawn(io_service, [&io_service](boost::asio::yield_context yield){
                    boost::asio::system_timer timer(io_service);
                    timer.expires_from_now(std::chrono::seconds(1));
                    timer.async_wait(yield);
                    cout << "Sleep 1 second" << endl;
                });
            });
        }
        else{
            boost::asio::spawn(io_service, [&io_service](boost::asio::yield_context yield){
                boost::asio::system_timer timer(io_service);
                timer.expires_from_now(std::chrono::seconds(1));
                timer.async_wait(yield);
                cout << "Sleep 1 second" << endl;
            });
        }
        boost::asio::system_timer timer(io_service);
        timer.expires_from_now(std::chrono::seconds(2));
        timer.async_wait(yield);
        cout << "Sleep 2 seconds" << endl;
    });
    io_service.run();
    return 0;
}

use_post 变量设置为 true,新的 stackfull 协程将通过 post + spawn 启动。

也许我没有仔细阅读文档,我在Boost.Asio C++ Network ProgrammingN4045 和boost asio 文档中找不到任何有用的东西。

最佳答案

这是安全的。

Boost.Asio 对 Boost.Coroutine 的一流支持是一个具有两个显着行为的薄外观:

  • 协程和恢复它的处理程序使用 strand他们的执行上下文。这保证协程在屈服之前不会被恢复。
  • Boost.Asio 可防止协程在检测到没有可用于恢复它的处理程序时无限期挂起。发生这种情况时,Boost.Asio 将销毁协程,导致挂起的堆栈展开。参见 this回答更多详情。

在上面的示例代码中,spawn(io_service&)重载导致生成的协程有自己的 strand。因此,如果多个线程正在运行 io_service,则每个协程都可以并行运行,但不能保证这样做。另一方面,如果使用 spawn(yield_context)重载时,新协程将具有与调用协程相同的执行上下文(即 strand),从而防止并行执行。

关于c++ - 在 asio stackful 协程中直接使用 spawn 是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29180589/

相关文章:

python - 将 python、numpy 和 scipy 代码转换为 C++ 兼容代码?

c++ - Boost错误代码人类可读的描述

c++ - 如何使用C++的选择性打开特性?

c++ - mfc - 富文本消息框

c++ - 如何保持 boost asio async 连续读取事件

python - Boost不将模块暴露给python

python - 无法在 Windows 7 中安装图形工具

c++ - boost::asio::signal_set 不恢复以前的信号处理程序

c++ - 高频接收UDP包 : packet loss?

c++ - 构建最大的堆叠塔与集团和限制