提升io_service非阻塞并行执行?

时间:2015-01-04 20:09:57

标签: c++ multithreading asynchronous boost

使用boost :: asio和boost :: io_service

时,我遇到了两难境地

我的类环绕了由套接字连接提供的async client example。 我使用另一个封装的类:

class service_controller
{
    ...

    /// IO service
    boost::asio::io_service __io_service;

    /// Endpoint Resolver
    boost::asio::ip::tcp::resolver::query __query;

    /// Resolution for TCP
    boost::asio::ip::tcp::resolver __resolver;
}

因此,当我构造我的客户端时,构造函数接受引用:

asio_service_client (
                        boost::asio::ip::tcp::resolver::query & query,
                        boost::asio::ip::tcp::resolver & resolver,
                        boost::asio::io_service & io_service
                    );

一切正常,但我必须致电

  

io_service.run()

最后,在创建了所有客户之后。 如果我为每个客户端封装单独的io_service对象,我基本上删除了异步io性质,因为每个客户端将阻塞直到它完成。 因此,我决定通过使所有客户端对象使用相同的io_service来形成一种类型的组。

io_service :: poll()似乎根本不起作用(没有任何反应),io_service :: run_one()也没有。

事实上,唯一可行的方法是:

    // with a callback => the callback will run once finished
    rapp::services::asio_service_client c1( ctrl.Query(), ctrl.Resolver(), ctrl.Services() );

    // without a callback => asio_service_client::handle_reply will run once finished
    rapp::services::asio_service_client c2 ( ctrl.Query(), ctrl.Resolver(), ctrl.Services() );
    rapp::services::asio_service_client c3 ( ctrl.Query(), ctrl.Resolver(), ctrl.Services() );
    rapp::services::asio_service_client c4 ( ctrl.Query(), ctrl.Resolver(), ctrl.Services() );

    // Run services c1, c2
    c1.Run( header, post,
            [&]( boost::asio::streambuf & buffer )
            { 
                std::string raw ( ( std::istreambuf_iterator<char>( &buffer ) ), std::istreambuf_iterator<char>() );
                std::cout << raw << std::endl;
            });

    c2.Run( header, post );
    ctrl.Services().run();

    /// Run remaining services ( c3, c4 )
    c3.Run( header, post );
    c4.Run( header, post );

    ctrl.Services().reset();
    ctrl.Services().run();

当然,除非我要求一个小组完全运行(例如,要求c1,c2,c3和c4运行)。

是否有某种方式或某种类模式,我可以自动化队列,在那里我创建对象,添加它们,它们是异步运行的?理想情况下使用线程,但没有线程也可以工作。

某种堆栈,在我添加对象时,它们会被异步执行,因为它们被添加。

如果我尝试这样的话:

Scheduler::Execute ( asio_service_client & client )
{
   client.Run( ... )
   io_service.reset();
   io_service.run();
}

我将重置以前运行的服务,并从头开始,这不是我想要的。 我唯一明显的选择是接受并为每个添加的asio_service_client分配一个单独的io_service,还是强制它们在作业组中一起添加,然后执行?

我能想到的另一个解决方案是使用线程,因此,每个asio_service_client都会在自己的线程中运行,因此不会阻止其他asio_service_clients,并行执行?

1 个答案:

答案 0 :(得分:2)

您可能希望共享一个io_service实例并在其上发布io_service::work对象,以便即使没有客户端当前有任何挂起的asycn操作,它也会保持活动状态:

boost::asio::io_service io_service;
auto work = boost::make_shared<boost::asio::io_service::work>(io_service);

// any client can post it's asynchronous operations on this service object, from any thread

// completion handlers will be invoked on any thread that runs `io_service.run()`

// once you want the `io_service` to empty the queue and return:
work.reset();

// now `run()` will return when it runs out of queued tasks