boost asio异步等待条件变量
是否可以对 boost::asio 中的条件变量执行异步等待(读取:非阻塞)?如果不直接支持任何有关实现的提示,我们将不胜感激。
我可以实现一个计时器,甚至每隔几毫秒就触发一次唤醒,但这种方法要差得多,我发现很难相信条件变量同步没有实现/记录。
Is it possible to perform an asynchronous wait (read : non-blocking) on a conditional variable in boost::asio ? if it isn't directly supported any hints on implementing it would be appreciated.
I could implement a timer and fire a wakeup even every few ms, but this is approach is vastly inferior, I find it hard to believe that condition variable synchronization is not implemented / documented.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果我正确理解了意图,那么当某个条件变量发出信号时,您想在 asio 线程池的上下文中启动事件处理程序吗?我认为在处理程序开头等待条件变量就足够了,并且 io_service::post() 本身最终回到池中,类似这样:
If I understand the intent correctly, you want to launch an event handler, when some condition variable is signaled, in context of asio thread pool? I think it would be sufficient to wait on the condition variable in the beginning of the handler, and io_service::post() itself back in the pool in the end, something of this sort:
我可以建议基于 boost::asio::deadline_timer 的解决方案,它对我来说效果很好。这是 boost::asio 环境中的一种异步事件。
一件非常重要的事情是“handler”必须通过与“cancel”相同的“strand_”进行序列化,因为从多个线程使用“boost::asio::deadline_timer”不是线程安全的。
I can suggest solution based on boost::asio::deadline_timer which works fine for me. This is kind of async event in boost::asio environment.
One very important thing is that the 'handler' must be serialised through the same 'strand_' as 'cancel', because using 'boost::asio::deadline_timer' from multiple threads is not thread safe.
不幸的是,Boost ASIO 没有
async_wait_for_condvar()
方法。在大多数情况下,您也不需要它。以 ASIO 方式编程通常意味着您使用链,而不是互斥体或条件变量来保护共享资源。除了极少数情况(通常关注启动和退出时的正确构造或销毁顺序)之外,您根本不需要互斥体或条件变量。
修改共享资源时,经典的部分同步线程方式如下:
完全异步 ASIO方式是:
下面是一个类
some_shared_resource
的示例,它接收字符串state
并根据收到的状态触发一些进一步的处理。请注意,私有方法some_shared_resource::receive_state()
中的所有处理都是完全线程安全的,因为链会序列化所有调用。当然,这个例子并不完整;
some_other_resource
需要一个与some_shared_ressource::send_state()
类似的send_code_red()
方法。正如您所看到的,一开始总是在 ASIO 的链中发帖可能会有点乏味。但是您可以将大部分“为类配备链”代码移至模板中。
消息传递的好处是:由于您不使用互斥体,因此即使在极端情况下,您也不会再陷入僵局。此外,使用消息传递通常比传统的多线程更容易创建高级别的并行性。不利的一面是,移动和复制所有这些消息对象非常耗时,这可能会减慢应用程序的速度。
最后一点:在
send_state()
形成的消息中使用弱指针有助于可靠地销毁some_shared_resource
对象:否则,如果 A 调用 B 并且 B 调用 C 和 C调用 A (可能仅在超时或类似之后),在消息中使用共享指针而不是弱指针将创建循环引用,从而防止对象销毁。如果您确定永远不会有循环,并且处理来自要删除对象的消息不会造成问题,则可以使用shared_from_this()
而不是weak_from_this( )
,当然。如果您确定在 ASIO 停止之前对象不会被删除(并且所有工作线程都连接回主线程),那么您也可以直接捕获this
指针。Unfortunately, Boost ASIO doesn't have an
async_wait_for_condvar()
method.In most cases, you also won't need it. Programming the ASIO way usually means, that you use strands, not mutexes or condition variables, to protect shared resources. Except for rare cases, which usually focus around correct construction or destruction order at startup and exit, you won't need mutexes or condition variables at all.
When modifying a shared resource, the classic, partially synchronous threaded way is as follows:
The fully asynchronous ASIO way is though:
Here is an example of a class
some_shared_resource
, that receives a stringstate
and triggers some further processing depending on the state received. Please note, that all processing in the private methodsome_shared_resource::receive_state()
is fully thread-safe, as the strand serializes all calls.Of course, the example is not complete;
some_other_resource
needs a similiarsend_code_red()
method assome_shared_ressource::send_state()
.As you see, posting always into ASIO's strands can be a bit tedious at first. But you can move most of that "equip a class with a strand" code into a template.
The good thing about message passing: As you are not using mutexes, you cannot deadlock yourself anymore, even in extreme situations. Also, using message passing, it is often easier to create a high level of parallelity than with classical multithreading. On the downside, moving and copying around all these message objects is time consuming, which can slow down your application.
A last note: Using the weak pointer in the message formed by
send_state()
facilitates the reliable destruction ofsome_shared_resource
objects: Otherwise, if A calls B and B calls C and C calls A (possibly only after a timeout or similiar), using shared pointers instead of weak pointers in the messages would create cyclic references, which then prevents object destruction. If you are sure, that you never will have cycles, and that processing messages from to-be-deleted objects doesn't pose a problem, you can useshared_from_this()
instead ofweak_from_this()
, of course. If you are sure, that objects won't get deleted before ASIO has been stopped (and all working threads been joined back to the main thread), then you can also directly capture thethis
pointer instead.FWIW,我使用相当好的 continuable 库实现了异步互斥体:
用法例如:
FWIW, I implemented an asynchronous mutex using the rather good continuable library:
usage eg: