Boost.Asio网络库之io_service分析
Posted shiyicode
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Boost.Asio网络库之io_service分析相关的知识,希望对你有一定的参考价值。
io_service概述
几乎绝大多数用到Boost.Asio的代码里都会出现这样一个类:io_service。它应该算是Asio库里的核心类了,其本质是一个任务队列,但又不仅仅是个任务队列。
基本结构
io_service是个接口类(ps:这里解释一下,这里说接口类并不是指类似java的interface类,而是指其是对下层类做了一个包装,全部功能都是调用下层类来完成)。
class io_service : private noncopyable
private:
typedef detail::io_service_impl impl_type;
...
上述代码中的impl_type即是我们所说的下层类,io_service的所有操作都是由它代为执行的。
这么说,为了实现跨平台,我们在io_service提供统一的操作接口,而不管平台的差异,impl_type的实现上分为两部分,
window系平台:win_iocp_io_service
非window系平台:task_io_service
使用宏定义根据平台来决定将哪个类作为具体执行类,见源码
#if defined(BOOST_ASIO_HAS_IOCP)
typedef class win_iocp_io_service io_service_impl;
class win_iocp_overlapped_ptr;
#else
typedef class task_io_service io_service_impl;
#endif
代码一目了然,不做赘述。
之前也学习过跨平台游戏引擎cocos2dx的部分源码,发现跨平台的开源库几乎都是类似的思想,用宏定义做到根据平台不同使用不同类来执行功能,在此之上提供接口,屏蔽平台差异。
我们这里只讨论task_io_service对应的功能。
功能
上面我们说过,io_service类的本质是一个任务队列,所谓任务队列,其实就是一个队列容器而已,其内部元素为void型的函数,我们将这些函数抽象看待为任务。(ps:既然是任务队列的模式,就当然会有锁的存在,而这个锁也被许多asio的使用者看做是眼中钉肉中刺,)
io_service提供了不少方法,在这里我们具体讨论最常用也是最核心的三个方法
run,run_one
run函数的功能是:执行队列的所有任务直到全部完成。
它应该是使用的最多的一个函数,因为当我们使用io_service注册异步事件后,需要执行run函数阻塞执行任务,否则程序可能会在任务未完成时就结束。
我们来看看其源码
std::size_t task_io_service::run(boost::system::error_code& ec)
ec = boost::system::error_code();
if (outstanding_work_ == 0)
stop();
return 0;
thread_info this_thread;
this_thread.private_outstanding_work = 0;
thread_call_stack::context ctx(this, this_thread);
mutex::scoped_lock lock(mutex_);
std::size_t n = 0;
for (; do_run_one(lock, this_thread, ec); lock.lock())
if (n != (std::numeric_limits<std::size_t>::max)())
++n;
return n;
outstanding_work_是一个原子变量,通过对它的值的修改来控制run函数是否直接结束。
run_one由名字就可想而知了,它只执行任务队列里的一个任务。
在执行任务时,如果有空闲线程,直接使用该线程去执行任务(领导者追随者模式),如果没有且监听事件的线程正在运行,则将阻塞时间变为0,即边监听边执行,待任务执行完毕在阻塞在epoll_wait上。当任务执行完后,再将监听模式改为阻塞。
poll,poll_one
这两组函数和run/run_one函数的功能完全一样,只是run/run_one函数执行是阻塞的,而poll函数是非阻塞的,所以在使用poll函数时要特别注意变量或对象的生命周期。
post
stop
退出,停止工作
未完待续
以上是关于Boost.Asio网络库之io_service分析的主要内容,如果未能解决你的问题,请参考以下文章
Boost::Asio : io_service.run() vs poll() 或者我如何在主循环中集成 boost::asio
boost::asio io_service 和 std::containers 的线程安全