为BOOST的ASIO增加“条件变量”实现协程间通讯

boost.asio提供了大量的async_*系方法来实现异步操作,配合协程使用非常简单粗暴。

但是实际使用过程中遇到了这样的情况:

已知若干个客户端(下文记作client)向一个队列(下文记作bus)投递消息,如何编程并保证队列不过载、数据不丢失?

如果使用协程来写,这个问题可以非常简单:

这是一个很典型的消费者/生产者模式,其中消费者和生产者的比例是1:N。通常而言,在多线程环境下消费者/生产者模式可以靠条件变量去实现,用作消息通知。

因此,只要自行实现write_to_bus和read_from_bus,使用一种类似“条件变量”的东西在必要的时候挂起和唤醒协程就好。

但是查阅google,翻阅boost.asio,却没能找到这样一种能用于协程间通知事件的东西。相同的问题在stackoverflow上也有好几个,有用deadline_timer去做workaround的,却没有比较好的解决方法。

既然如此,那就只能自己来设计了。由于boost.asio的封装较为复杂,在翻阅源码后可以简单的知道:

  1. boost::asio::handler_type<CompletionToken, Signature>用于获取handler的包装来唤醒协程;
  2. boost::asio::async_result<Handler>用于挂起协程;
  3. boost::asio::asio_handler_invoke根据调用环境上下文来唤起协程。

直接贴代码:

编译条件:g++ test.cpp -lboost_system -lboost_coroutine -I/usr/local/Cellar/boost/1.59.0/include -L/usr/local/lib/ -o test -std=c++11

这样,实现了一个条件变量来进行协程间的通信。

 

鸣谢

C君(@nadesico19)在boost协程库方面的帮助。

参考

  1. stackoverflow: http://stackoverflow.com/questions/26694423/how-resume-the-execution-of-a-stackful-coroutine-in-the-context-of-its-strand
  2. github: https://github.com/godexsoft/push_service/blob/master/src/push/detail/async_condition_variable.hpp
  3. 贴吧老物: http://tieba.baidu.com/p/3228889662?pid=55596731732
chu's box · 浙ICP备14006917号