开发者社区> 北之燕> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Boost::asio io_service 实现分析

简介: Boost::asio io_service 实现分析 io_service的作用 io_servie 实现了一个任务队列,这里的任务就是void(void)的函数。Io_servie最常用的两个接口是post和run,post向任务队列中投递任务,run是执行队列中的任务,直到全部执行完毕,并且run可以被N个线程调用。
+关注继续查看

Boost::asio io_service 实现分析

io_service的作用

io_servie 实现了一个任务队列,这里的任务就是void(void)的函数。Io_servie最常用的两个接口是postrunpost向任务队列中投递任务,run是执行队列中的任务,直到全部执行完毕,并且run可以被N个线程调用。Io_service是完全线程安全的队列。

Io_servie的接口

提供的接口有runrun_onepollpoll_onestopresetdispatchpost,最常用的是runpoststop

Io_servie 实现代码的基本类结构:

l  Io_servie是接口类,为实现跨平台,采用了策略模式,所有接口均有impl_type实现。根据平台不同impl_type分为

n  win_iocp_io_service Win版本的实现,这里主要分析Linux版本。

n  task_io_service win平台下的实现,其代码结构为:

u  detail/task_io_service_fwd.hpp 简单声明task_io_service名称

u  detail/task_io_service.hpp 声明task_io_service的方法和属性

u  detail/impl/task_io_service.ipp 具体实现文件

u  队列中的任务类型为opertioan,原型其实是typedef task_io_service_operation operation,其实现文件在detail/task_io_service_operation.hpp中,当队列中的任务被执行时,就是task_io_service_operation:: complete被调用的时候。

Io_servie::Post方法的实现

Post向队列中投递任务,然后激活空闲线程执行任务。其实现流程如下:

l  Post接收handler作为参数,实际上是个仿函数,通过此仿函数构造出completion_handler对象,completion_handler继承自operation。然后调用post_immediate_completion

l  post_immediate_completion首先将outstanding_work_增加,然后调用post_deferred_completion

l  post_deferred_completion首先加锁将任务入列,然后调用wake_one_thread_and_unlock

l  wake_one_thread_and_unlock尝试唤醒当前空闲的线程,其实现中特别之处在于,若没有空闲线程,但是有线程在执行task->run,即阻塞在epoll_wait上,那么先中断epoll_wait执行任务队列完成后再执行epoll_wait

l  first_idle_thread_维护了所有当前空闲线程,实际上使用了Leader/Follower模式,每次唤醒时只唤醒空闲线程的第一个。

Io_servie::run方法的实现

         Run方法执行队列中的所有任务,直到任务执行完毕。

l  run方法首先构造一个idle_thread_info,和first_idle_thread_类型相同,即通过first_idle_thread_将所有线程串联起来,它这个串联不是立即串联的,当该线程无任务可做是加入到first_idle_thread_的首部,有任务执行时,从first_idle_thread_中断开。这很正常,因为first_idle_thread_维护的是当前空闲线程。

l  加锁,循环执行do_one方法,直到do_one返回false

l  do_one每次执行一个任务。首先检查队列是否为空,若空将此线程追加到first_idle_thread_的首部,然后阻塞在条件变量上,直到被唤醒。

l  当被唤醒或是首次执行,若stopped_true(即此时stop方法被调用了),返回0

l  队列非空,pop出一个任务,检查队列无任务那么简单的解锁,若仍有,调用wake_one_thread_and_unlock尝试唤醒其他空闲线程执行。然后执行该任务,返回1.

l  实际上在执行队列任务时有一个特别的判断if (o == &task_operation_),那么将会执行task_->runtask_变量类型为reactor,在linux平台实现为epoll_reactor,实现代码文件为detail/impl/epoll_reactor.ipprun方法实际上执行的是epoll_waitrun阻塞在epoll_wait上等待事件到来,并且处理完事件后将需要回调的函数pushio_servie的任务队列中,虽然epoll_wait是阻塞的,但是它提供了interrupt函数,该interrupt是如何实现的呢,它向epoll_wait添加一个文件描述符,该文件描述符中有8个字节可读,这个文件描述符是专用于中断epoll_wait的,他被封装到select_interrupter中,select_interrupter实际上实现是eventfd_select_interrupter,在构造的时候通过pipe系统调用创建两个文件描述符,然后预先通过write_fd8个字节,这8个字节一直保留。在添加到epoll_wait中采用EPOLLET水平触发,这样,只要select_interrupter的读文件描述符添加到epoll_wait中,立即中断epoll_wait。很是巧妙。!!!实际上就是因为有了这个reactor,它才叫io_servie,否则就是一个纯的任务队列了。

l  Run方法的原则是:

n  有任务立即执行任务,尽量使所有的线程一起执行任务

n  若没有任务,阻塞在epoll_wait上等待io事件

n  若有新任务到来,并且没有空闲线程,那么先中断epoll_wait,先执行任务

n  若队列中有任务,并且也需要epoll_wait监听事件,那么非阻塞调用epoll_waittimeout字段设置为0),待任务执行完毕在阻塞在epoll_wait上。

n  几乎对线程的使用上达到了极致。

n  从这个函数中可以知道,在使用ASIO时,io_servie应该尽量多,这样可以使其epoll_wait占用的时间片最多,这样可以最大限度的响应IO事件,降低响应时延。但是每个io_servie::run占用一个线程,所以io_servie最佳应该和CPU的核数相同。

Io_servie::stop的实现

l  加锁,调用stop_all_threads

l  设置stopped_变量为true,遍历所有的空闲线程,依次唤醒

l  task_interrupted_设置为true,调用task_interrupt方法

l  task_的类型为reactor,在run方法中已经做了分析

l 

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Webservice工作原理及实例
Webservice工作原理及实例 一、Web Service基本概念   Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。
2081 0
【Boost】boost库asio详解2——io_service::run函数无任务时退出的问题
io_service::work类可以使io_service::run函数在没有任务的时候仍然不返回,直至work对象被销毁。 [cpp] view plain copy    print? void test_asio_nowork()   {       b...
1299 0
webService客户端 (spring MVC实现)
获得 即springMVC。 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.0.6.RELEASE</version> </depe
1233 0
跟据URL来实现WebService
 [WebMethod]        public string GetResults(string word)        {            string resultHtml = string.
491 0
用POJO实现0配置的WebService
Axis2是一套崭新的WebService引擎,该版本是对Axis1.x重新设计的产物。Axis2不仅支持SOAP1.1和SOAP1.2,还集成了非常流行的REST WebService,同时还支持Spring、JSON等技术。
578 0
+关注
北之燕
游戏服务器主程,热爱技术热爱生活,现在专注于开源游戏服务器框架。
63
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载