在asio stackfull协程中直接使用spawn是安全的吗? [英] Is it safe to use spawn directly in an asio stackfull coroutine?

查看:747
本文介绍了在asio stackfull协程中直接使用spawn是安全的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用spawn在协程中启动一个新的stackfull协同程序时,valgrind说大量使用未初始化的值( valgrind输出)。



然后我使用io_service.post调用处理程序,并启动一个新的stackfull协同程序,每一件事情看起来很好。 p>

我已经搜索并读取了一些文档,但是找不到关于如何在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<第二个<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秒< endl;
});
}
boost :: asio :: system_timer timer(io_service);
timer.expires_from_now(std :: chrono :: seconds(2));
timer.async_wait(yield);
cout<< 睡眠2秒< endl;
});
io_service.run();
return 0;
}

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



也许我不仔细阅读文档,我不能在 Boost.Asio C ++网络编程 N4045 和boost asio文档。



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




  • 协程和处理程序恢复使用 strand

  • Boost.Asio会阻止协同程序如果检测到没有可用的恢复程序而无限期地暂停。当这种情况发生时,Boost.Asio将破坏协程,导致暂停的堆栈解开。有关详情,请参见答案。



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


When I use spawn to start a new stackfull coroutine in a coroutine, valgrind says a lot of using uninitialised value(valgrind output).

Then I use io_service.post to invoke a handler,and start a new stackfull coroutine in it, every thing seems fine.

I have searched and read some documents, but can't find something about how to create a new stackfull coroutine safely in a stackfull coroutine.

Here is the code:

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

set true to use_post variable, new stackfull coroutine will be started by post + spawn.

Maybe I don't read the documents carefully, i can't find any thing usefull in Boost.Asio C++ Network Programming, N4045 and boost asio document.

解决方案

It is safe.

Boost.Asio's first-class support for Boost.Coroutine is a thin facade with two notable behaviors:

  • A coroutine and handlers which resume it use a strand for their execution context. This guarantees the coroutine will not be resumed before it has yielded.
  • Boost.Asio prevents a coroutine from staying indefinitely suspended if it detects that there are no handlers available to resume it. When this occurs, Boost.Asio will destroy the coroutine, causing the suspended stack to unwind. See this answer for more details.

In the example code above, the spawn(io_service&) overload causes the resulting coroutine to have its own strand. As a result, if multiple threads are running the io_service, each of the coroutines may run in parallel, but are not guaranteed to do so. On the other hand, if one uses the spawn(yield_context) overload, the new coroutine will have the same execution context (i.e strand) as the calling coroutine, preventing parallel execution.

这篇关于在asio stackfull协程中直接使用spawn是安全的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆