我已经看到了其他StackOverflow问题boost asio asynchronously waiting on a condition variable,boost::asio async condition和boost condition variable issue,但这些问题/答案中没有一个能够令人满意地触及我所拥有的一个基本问题:Boost.Asio是否属实,和/或是否存在根本原因不适用于条件变量,或与条件变量自然吻合?
我的想法是条件变量是使用操作系统级同步对象在内部实现的(例如,Windows上的boost :: thread :: condition_variable使用Windows操作系统信号量).因为,根据我目前的理解,boost :: asio :: io_service旨在封装操作系统级别的同步对象,因此条件变量似乎很自然.
确实,与文件操作和套接字操作不同,在操作系统级别通常从不存在与信号条件相关联的回调函数(我认为 – 我不确定这一点).但是,在Boost.Asio中实现这样的回调处理程序似乎很简单,只需要用户提供一个回调函数,该函数在条件变量发出信号时被调用 – 正如用户必须为其他函数提供完成处理程序例程一样. boost :: asio :: io_service服务.
例如(这只是一个快速思考,而不是一个完整的原型 – 它没有包含足够的参数来处理notify_one()与notify_all(),没有说明服务如何知道何时退出,并且可能有其他明显的遗漏或缺陷):
void condition_handler_function() {} boost::asio::io_service service; boost::mutex mut; boost::condition_variable cond; // The following class is **made up by me** - would such a class be a good idea? boost::asio::io_service::condition_service condserv(service,cond,mut,condition_handler_function); condserv.async_wait_on_signal(); service.run(); // when condition variable is signaled by notify_one(),// 'handler_function()' would be called // ... in some other thread,later: cond.notify_one(); // This would trigger 'handler_function()' // in this theoretical code
也许,如果我试图填写代码片段上面提到的缺失细节,我会清楚地知道这不能以干净的方式工作.但是,这项工作并非易事.
因此,我想在这里发布问题.有没有充分的理由说明Boost.Asio不支持条件变量?
附录
我已经将帖子的标题更改为引用“基于事件的界面”,因为Tanner的答案在下面向我阐明了它实际上是一个基于事件的界面,我正在询问(不是真正的条件变量).
解决方法
由于操作启动和完成之间的时间和空间分离,异步编程已经具有固有的复杂性. Strands提供了一个相当干净的解决方案,可以提供严格的顺序调用处理程序,而无需显式锁定.由于锁定既是隐式的又是线程安全的,因此应用程序代码可以使用链而不必担心死锁.另一方面,让boost :: asio :: io_service :: condition_service对外部提供的对象执行隐式同步可能会使复杂的库变为复杂的库.应用程序开发人员可能不清楚处理程序同步的互斥锁以及互斥锁的状态.此外,它还引入了应用程序由于隐式锁定而更容易使事件处理循环死锁的能力.
如果需要进行基于事件的处理程序调用,那么一个相当简单的替代方法是使用相同的方法Boost.Asio的timeout server示例使用:boost::asio::deadline_timer
. deadline_timer的到期时间可以设置为posix_time :: pos_infin,导致只调用async_wait
的处理程序一旦计时器被取消:
> cancel()
可以作为notify_all(),其中所有未完成的处理程序排队等待调用.
> cancel_one()
可以用作notify_one(),其中最多一个未完成的处理程序排队等待调用.
#include <iostream> #include <boost/asio.hpp> #include <boost/thread.hpp> class event { public: explicit event(boost::asio::io_service& io_service) : timer_(io_service) { // Setting expiration to infinity will cause handlers to // wait on the timer until cancelled. timer_.expires_at(boost::posix_time::pos_infin); } template <typename WaitHandler> void async_wait(WaitHandler handler) { // bind is used to adapt the user provided handler to the deadline // timer's wait handler type requirement. timer_.async_wait(boost::bind(handler)); } void notify_one() { timer_.cancel_one(); } void notify_all() { timer_.cancel(); } private: boost::asio::deadline_timer timer_; }; void on_event() { std::cout << "on_event" << std::endl; } int main() { boost::asio::io_service io_service; event event(io_service); // Add work to service. event.async_wait(&on_event); // Run io_service. boost::thread thread(boost::bind(&boost::asio::io_service::run,&io_service)); // Trigger event,causing the on_event handler to run. event.notify_one(); thread.join(); }