boost.asio源码阅读(2) - task_io_service
1.0 task_io_service
在boost.asio源码阅读(1)中,代码已经查看到task_io_service中。
具体的操作调用void task_io_service::init_task()
本文从init_task出发,查看到底basic_socket_acceptor的创建对task_io_service产生了什么影响.
1.1 init_task
直接上代码
void task_io_service::init_task()
{
mutex::scoped_lock lock(mutex_);
if (!shutdown_ && !task_)
{
1. task_ = &use_service<reactor>(this->get_io_service());
2. op_queue_.push(&task_operation_);
3. wake_one_thread_and_unlock(lock);
}
}
- 创建task_,其实task_就是epoll_reactor.
- 将成员task_operation_放入队列
- 唤醒一个线程,并对当前操作解锁。
这里能够明确io_service使用了同步队列op_queue(lock->入队->唤醒->unlock),在basic_socket_acceptor
创建时,将task_operation_放入队列,在io_service->run()中,这个变量将会被操作.
1.2 task_io_service::run
直奔主题
std::size_t task_io_service::run(boost::system::error_code& ec)
{
// ......
thread_info this_thread;
this_thread.private_outstanding_work = 0;
// ......
for (; do_run_one(lock, this_thread, ec); lock.lock())
//......
}
thread_info 内部含有一个队列,也就是说在多线程调用io_service::run的时候
每一个线程将会具有自己的私有队列。
std::size_t task_io_service::do_run_one
{
while (!stopped_)
{
if (!op_queue_.empty())
{
// Prepare to execute first handler from queue.
operation* o = op_queue_.front();
op_queue_.pop();
bool more_handlers = (!op_queue_.empty());
1. if (o == &task_operation_)
{
task_interrupted_ = more_handlers;
if (more_handlers && !one_thread_)
wakeup_event_.unlock_and_signal_one(lock);
else
lock.unlock();
2. task_cleanup on_exit = { this, &lock, &this_thread };
(void)on_exit;
task_->run(!more_handlers, this_thread.private_op_queue);
}
else
{
std::size_t task_result = o->task_result_;
if (more_handlers && !one_thread_)
wake_one_thread_and_unlock(lock);
else
lock.unlock();
// Ensure the count of outstanding work is decremented on block exit.
4. work_cleanup on_exit = { this, &lock, &this_thread };
(void)on_exit;
// Complete the operation. May throw an exception. Deletes the object.
o->complete(*this, ec, task_result);
return 1;
}
}
else
{
wakeup_event_.clear(lock);
5. wakeup_event_.wait(lock);
}
}
return 0;
}
- 如果当前操作的队列内容是task_operation_则最后会进入到task_->run也就是epoll_wait。
同时,如果当前队列不为空且是多线程的时候,会继续唤醒线程来执行操作,避免epoll_wait阻赛带来的延迟(虽然可以打断)。
到这里可以知道basic_socket_acceptor的创建使io_service->run的时候可以进入epoll_wait来处理相关的事件, - 和line4相同,都是在定义一个变量后,执行对应的析构操作。同时将线程的私有队列的内容,添加到公有队列op_queue_中,最后将刚才出队的task_operation_重新加到队尾(task_cleanup),使io_service在处理完队列之前的事件后,再次进入到task->run中。
- line5表示在队列为空时,线程进入睡眠等待唤醒。
2. 小结
- 在本文中,可以知道basic_socket_acceptor的创建使io_service在循环事件时能够进入到epoll_wait。
当然如果这时使用者将acceptor删除也不能改变io_service->run本身的逻辑,也就是说,如果acceptor不在需要,io_service要么停止或者重新开始,避免epoll_wait上面不必要的效率损失。 - task_io_service本身有一个公共队列,同时每一个执行线程有自己的私有队列,在每次处理事件之前,会将
私有队列的内容先加入到公有队列中。在某种程度上,公有队列的内容要比私有队列的优先级高些。 - asio的所有事件,最后都会回到公有队列中等待被执行。
boost.asio源码阅读(2) - task_io_service的更多相关文章
- boost.asio源码阅读(1) - 从chat_server开始
1. 关于示例代码 chat 先从简单的入手, 在如下路径:boost_1_63_0/libs/asio/example/cpp11/chat中找到chat_server.cpp 查看其成员, pri ...
- boost.asio源码剖析(一) ---- 前 言
* 前言 源码之前,了无秘密. ——侯捷 Boost库是一个可移植.提供源代码的C++库,作 ...
- boost.asio源码剖析(三) ---- 流程分析
* 常见流程分析之一(Tcp异步连接) 我们用一个简单的demo分析Tcp异步连接的流程: #include <iostream> #include <boost/asio.hpp& ...
- boost.asio源码剖析(五) ---- 泛型与面向对象的完美结合
有人说C++是带类的C:有人说C++是面向对象编程语言:有人说C++是面向过程与面向对象结合的语言.类似的评论网上有很多,虽然正确,却片面,是断章取义之言. C++是实践的产物,C++并没有为了成为某 ...
- boost.asio源码剖析(四) ---- asio中的泛型概念(concepts)
* Protocol(通信协议) Protocol,是asio在网络编程方面最重要的一个concept.在第一章中的levelX类图中可以看到,所有提供网络相关功能的服务和I/O对象都需要Protoc ...
- boost.asio源码剖析(二) ---- 架构浅析
* 架构浅析 先来看一下asio的0层的组件图. (图1.0) io_object是I/O对象的集合,其中包含大家所熟悉的socket.deadline_tim ...
- boost.asio源码剖析
一. 前 言二. 架构浅析三. 流程分析 * 常见流程分析之一(Tcp异步连接) * 常见流程分析之二(Tcp异步接受连接) * 常见流程分析之三(Tcp异步读写数据) ...
- FreeCAD源码阅读笔记
本文目标在于记录在FreeCAD源码阅读中了解到的一些东西. FreeCAD编译 FreeCAD源码的编译最好使用官方提供的LibPack,否则第三方库难以找全,找到之后还需要自己编译,此外还不知道C ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
随机推荐
- CODEFORCES 125E MST Company 巧用Kruskal算法
题意:给定一个带权边无向图,求最小生成树,且满足第一个节点的度为固定的k 无解则输出-1 数据规模: 节点数n和限制k<=5000 边数m<=10^5 时限8sec 思路: 首先时限比较宽 ...
- win10下VS2015局域网调试配置
一.前言 换win10页挺久了一直没有使用 IISExpress 的局域网功能,今天一使用才发现 win10 比起 win7 下配置多了许多坑. 二.配置步骤 首先我们先来拿到本机 ip 地址 打开命 ...
- 制作jar文件
一.制作可运行jar文件 使用java的swing.awt制作了一个简单的界面交互模块.程序打成jar包后,能双击运行,制作过程: 1.eclipse →properties →Export,选择ja ...
- shell脚本,符号
在shell中常用的特殊符号罗列如下: # ; ;; . , / \\ 'string'| ! $ ${} $? $$ $* \"string\"* ** ...
- Swift 2.0 UIAlertView 和 UIActionSheet 的使用
在 IOS 9.0 之后, UIAlertView 是 给废弃了的,虽然你要使用的话,暂时还是可以的,但是在 9.0 之后,IOS 推荐大家使用的是 UIAlertController 这个控制器 ...
- matlab 逻辑数组及其应用
这几天学习了matlab的逻辑数组功能,总的感觉就有两点: 第一,通过对原来的数组a进行逻辑判断后得到逻辑数组b 第二,逻辑数组进行某种运算符操作又回到原数组类型 第三,利用逻辑数组mask功能 测试 ...
- C# 获取文件MD5与SHA1
之前刚开始学习编程的时候,总想着自己写一些小软件小工具. 而这个就是经典的文件MD5校验,顺便加上了一个SHA1. 在网络上下载一些东西时,会有作者提供MD5值. 它的作用就在于我们可以在下载该软件后 ...
- 浅谈PHP的CI框架(一)
作为前端开发人员,掌握一门后端语言是必不可少的,PHP的CI框架是一个快速开发框架,基于MVC,比较接近原生PHP,在原有的PHP代码上封装了许多类,易上手,容易扩展,适用于小项目,并且CI的文档及案 ...
- 简学Python第四章__装饰器、迭代器、列表生成式
Python第四章__装饰器.迭代器 欢迎加入Linux_Python学习群 群号:478616847 目录: 列表生成式 生成器 迭代器 单层装饰器(无参) 多层装饰器(有参) 冒泡算法 代码开发 ...
- zabbix安装详解
关于zabbix及相关服务软件版本: Linux:centos 6.6 nginx:1.9.15 MySQL:5.5.49 PHP:5.5.35 一.安装nginx: 安装依赖包: yum -y in ...