提升 io_service 非阻塞并行执行?
boost io_service non-blocking parallel execution?
我在使用 boost::asio 和 boost::io_service
时遇到了难题
我的 classes 围绕着 boost 为套接字连接提供的 async client example。
我使用另一个 class 封装:
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)。
是否有某种方式或某种 class 模式,我可以在其中自动创建一个队列,在其中创建对象,添加它们,然后它们异步运行?理想情况下有线程,但没有也可以。
某种堆栈,当我添加对象时,它们会在添加时异步执行。
如果我尝试类似的操作:
Scheduler::Execute ( asio_service_client & client )
{
client.Run( ... )
io_service.reset();
io_service.run();
}
我会重置之前运行的服务,重新开始,这不是我想要的。
我唯一明显的选择是接受并为每个添加的 io_service_client 分配一个单独的 io_service,或者强制将它们一起添加到一个作业组中,然后执行?
我能想到的另一个解决方案是使用线程,因此,每个 asio_service_client 将在自己的线程中运行,因此不会阻塞其他 asio_service_clients,执行并行?
您可能想要共享一个 io_service
实例和 post 上面的一个 io_service::work
对象,这样即使当前没有客户端有任何待处理的异步操作,它也会保持活动状态:
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
我在使用 boost::asio 和 boost::io_service
时遇到了难题我的 classes 围绕着 boost 为套接字连接提供的 async client example。 我使用另一个 class 封装:
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)。
是否有某种方式或某种 class 模式,我可以在其中自动创建一个队列,在其中创建对象,添加它们,然后它们异步运行?理想情况下有线程,但没有也可以。
某种堆栈,当我添加对象时,它们会在添加时异步执行。
如果我尝试类似的操作:
Scheduler::Execute ( asio_service_client & client )
{
client.Run( ... )
io_service.reset();
io_service.run();
}
我会重置之前运行的服务,重新开始,这不是我想要的。 我唯一明显的选择是接受并为每个添加的 io_service_client 分配一个单独的 io_service,或者强制将它们一起添加到一个作业组中,然后执行?
我能想到的另一个解决方案是使用线程,因此,每个 asio_service_client 将在自己的线程中运行,因此不会阻塞其他 asio_service_clients,执行并行?
您可能想要共享一个 io_service
实例和 post 上面的一个 io_service::work
对象,这样即使当前没有客户端有任何待处理的异步操作,它也会保持活动状态:
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