[英]Prevent boost::asio::io_context stopping on empty poll call
This code calls the posted handle此代码调用发布的句柄
boost::asio::io_context ioc;
boost::asio::post(ioc, []{ std::cout << "lol" << std::endl; });
ioc.poll();
whereas this doesn't:而这不是:
boost::asio::io_context ioc;
ioc.poll(); // empty, set internal state to stopped_
boost::asio::post(ioc, []{ std::cout << "lol" << std::endl; });
ioc.poll(); // doesn't work as stopped() now returns true
Is it by design?是设计使然吗? If is, why?
如果是,为什么? Can I configure
io_context
somehow to change this behavior?我可以以某种方式配置
io_context
来改变这种行为吗?
io_service/io_context are designed to stop when they run out of work¹. io_service/io_context 旨在在它们用完工作时停止¹。
The docs for io_service
and io_context
contain: io_service
和io_context
的文档包含:
Stopping the io_context from running out of work
阻止 io_context 耗尽工作
Some applications may need to prevent an io_context object's run() call from returning when there is no more work to do.
当没有更多工作要做时,某些应用程序可能需要阻止 io_context 对象的 run() 调用返回。 For example, the io_context may be being run in a background thread that is launched prior to the application's asynchronous operations.
例如,io_context 可能正在后台线程中运行,该线程在应用程序的异步操作之前启动。 The run() call may be kept running by creating an object of type boost::asio::executor_work_guard<io_context::executor_type>:
run() 调用可以通过创建 boost::asio::executor_work_guard<io_context::executor_type> 类型的 object 来保持运行:
boost::asio::io_context io_context; boost::asio::executor_work_guard<boost::asio::io_context::executor_type> = boost::asio::make_work_guard(io_context); ...
To effect a shutdown, the application will then need to call the io_context object's stop() member function.
为了实现关闭,应用程序需要调用 io_context 对象的 stop() 成员 function。 This will cause the io_context run() call to return as soon as possible, abandoning unfinished operations and without permitting ready handlers to be dispatched.
这将导致 io_context run() 调用尽快返回,放弃未完成的操作并且不允许调度准备好的处理程序。
Alternatively, if the application requires that all operations and handlers be allowed to finish normally, the work object may be explicitly reset.
或者,如果应用程序要求允许所有操作和处理程序正常完成,则可以显式重置工作 object。
boost::asio::io_context io_context; boost::asio::executor_work_guard<boost::asio::io_context::executor_type> = boost::asio::make_work_guard(io_context); ... work.reset(); // Allow run() to exit.
Note that the "old-fashioned" Asio interface used a less generalized io_service::work
object:请注意,“老式”的 Asio 接口使用了不太通用的
io_service::work
object:
io_service ios;
io_service::work work(ios); // old interface!
This would then require you to do extra work for to be able to reset it:这将需要您做额外的工作才能重置它:
asio::io_service ios;
std::optional<asio::io_service::work> work(ios);
// ...
work.reset();
Finally when the context did run out of work, you will have to restart()
it before re-using it:最后,当上下文确实耗尽工作时,您必须在重新使用它之前重新
restart()
它:
I think the rationale for the design comes from the library not having any opinions about how the service is run in terms of scheduling and threading, in combination with the guarantee that io_context
/ io_service
must be thread-safe².我认为设计的基本原理来自图书馆对服务在调度和线程方面的运行方式没有任何意见,同时保证
io_context
/ io_service
必须是线程安全的²。 See docs for background .有关背景,请参阅文档。
¹ Sidenote: Likewise, thread_pool
(which is-a execution_context
just like io_context
is) is not designed for re-use (see eg Boost asio thread_pool join does not wait for tasks to be finished ) ¹旁注:同样,
thread_pool
(这是一个execution_context
,就像io_context
一样)不是为重用而设计的(参见例如Boost asio thread_pool join does not wait for tasks to be completed )
² Except object lifetime (construction/destruction), of course ² 除了 object 寿命(构造/销毁),当然
This documented (not in best place, it should be mentioned in poll
documentation):这已记录在案(不是最好的地方,应该在
poll
文档中提及):
io_context::restart - develop io_context::restart - 开发
io_context::restartio_context::重启
Restart the
io_context
in preparation for a subsequentrun()
invocation.重新启动
io_context
为后续的run()
调用做准备。void restart();
无效重启();
This function must be called prior to any second or later set of invocations of the
run()
,run_one()
,poll()
orpoll_one()
functions when a previous invocation of these functions returned due to theio_context
being stopped or running out of work.此 function 必须在
run()
、run_one()
、poll()
或poll_one()
函数的任何第二组或以后调用之前调用,当这些函数的先前调用由于io_context
被停止或用完而返回时工作。 After a call torestart()
, theio_context
object'sstopped()
function will returnfalse
.调用
restart()
后,io_context
对象的stopped()
function 将返回false
。This function must not be called while there are any unfinished calls to the
run()
,run_one()
,poll()
orpoll_one()
functions.当对
run()
、run_one()
、poll()
或poll_one()
函数有任何未完成的调用时,不得调用此 function。
So basically you need to add restart
to make it work.所以基本上你需要添加
restart
才能让它工作。
https://wandbox.org/permlink/aXzz5GCAIMIvStnl https://wandbox.org/permlink/aXzz5GCAIMIvStnl
Here is an extra clue why.这是一个额外的线索为什么。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.