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);
}
}
  1. 创建task_,其实task_就是epoll_reactor.
  2. 将成员task_operation_放入队列
  3. 唤醒一个线程,并对当前操作解锁。

    这里能够明确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;
}
  1. 如果当前操作的队列内容是task_operation_则最后会进入到task_->run也就是epoll_wait。

    同时,如果当前队列不为空且是多线程的时候,会继续唤醒线程来执行操作,避免epoll_wait阻赛带来的延迟(虽然可以打断)。

    到这里可以知道basic_socket_acceptor的创建使io_service->run的时候可以进入epoll_wait来处理相关的事件,
  2. 和line4相同,都是在定义一个变量后,执行对应的析构操作。同时将线程的私有队列的内容,添加到公有队列op_queue_中,最后将刚才出队的task_operation_重新加到队尾(task_cleanup),使io_service在处理完队列之前的事件后,再次进入到task->run中。
  3. line5表示在队列为空时,线程进入睡眠等待唤醒。

2. 小结

  1. 在本文中,可以知道basic_socket_acceptor的创建使io_service在循环事件时能够进入到epoll_wait。

    当然如果这时使用者将acceptor删除也不能改变io_service->run本身的逻辑,也就是说,如果acceptor不在需要,io_service要么停止或者重新开始,避免epoll_wait上面不必要的效率损失。
  2. task_io_service本身有一个公共队列,同时每一个执行线程有自己的私有队列,在每次处理事件之前,会将

    私有队列的内容先加入到公有队列中。在某种程度上,公有队列的内容要比私有队列的优先级高些。
  3. asio的所有事件,最后都会回到公有队列中等待被执行。

boost.asio源码阅读(2) - task_io_service的更多相关文章

  1. boost.asio源码阅读(1) - 从chat_server开始

    1. 关于示例代码 chat 先从简单的入手, 在如下路径:boost_1_63_0/libs/asio/example/cpp11/chat中找到chat_server.cpp 查看其成员, pri ...

  2. boost.asio源码剖析(一) ---- 前 言

    * 前言 源码之前,了无秘密.                                                       ——侯捷 Boost库是一个可移植.提供源代码的C++库,作 ...

  3. boost.asio源码剖析(三) ---- 流程分析

    * 常见流程分析之一(Tcp异步连接) 我们用一个简单的demo分析Tcp异步连接的流程: #include <iostream> #include <boost/asio.hpp& ...

  4. boost.asio源码剖析(五) ---- 泛型与面向对象的完美结合

    有人说C++是带类的C:有人说C++是面向对象编程语言:有人说C++是面向过程与面向对象结合的语言.类似的评论网上有很多,虽然正确,却片面,是断章取义之言. C++是实践的产物,C++并没有为了成为某 ...

  5. boost.asio源码剖析(四) ---- asio中的泛型概念(concepts)

    * Protocol(通信协议) Protocol,是asio在网络编程方面最重要的一个concept.在第一章中的levelX类图中可以看到,所有提供网络相关功能的服务和I/O对象都需要Protoc ...

  6. boost.asio源码剖析(二) ---- 架构浅析

    * 架构浅析 先来看一下asio的0层的组件图.                     (图1.0) io_object是I/O对象的集合,其中包含大家所熟悉的socket.deadline_tim ...

  7. boost.asio源码剖析

    一. 前 言二. 架构浅析三. 流程分析     * 常见流程分析之一(Tcp异步连接)      * 常见流程分析之二(Tcp异步接受连接)      * 常见流程分析之三(Tcp异步读写数据)   ...

  8. FreeCAD源码阅读笔记

    本文目标在于记录在FreeCAD源码阅读中了解到的一些东西. FreeCAD编译 FreeCAD源码的编译最好使用官方提供的LibPack,否则第三方库难以找全,找到之后还需要自己编译,此外还不知道C ...

  9. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

随机推荐

  1. Unity3D中如何计算场景中的三角面和顶点数

    在做游戏开发时,场景中的三角面和顶点数影响着运行效率,尤其是在手机平台上,实时的知道场景中的各项指标,对性能优化来说至关重要,下面我们来实现一个小功能,来实时计算场景中的三角面和顶点数: 如果要知道场 ...

  2. secache 详解

    介绍下secache缓存,它是属于文件缓存.简单来说,文件缓存就是把缓存数据存储到文件系统 (硬盘)中了,比 内存缓存要慢一些,但是也是有一点优点的. 1.磁盘容量大, 2保存到硬盘,说明 掉电后数据 ...

  3. C++ Primer 笔记 第一章

    C++ Primer 学习笔记 第一章 快速入门 1.1 main函数 系统通过调用main函数来执行程序,并通过main函数的返回值确定程序是否成功执行完毕.通常返回0值表明程序成功执行完毕: ma ...

  4. WinForm——记住密码

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Runti ...

  5. Masonry的简单使用

    #import "RootViewController.h" #import "Masonry.h" @interface RootViewController ...

  6. j2se 总结

    j2se在学习第二遍的时候,感觉还是比较亲切的.

  7. matlab图像显示程序模板

    在这个程序中:优秀的模板值得学习,变量的定义字典值得学习 .^ .* ./的使用:        图形的显示及标注 % 脚本文件: 功率计算 % 文件名:cac_power.m % 目标:随着电阻值的 ...

  8. iOS UISearchController 的使用方法

    iOS UISearchController 的使用方法 UISearchController 让用户在 UISearchBar 上输入搜索关键词,展示搜索结果或者进行其他操作.UISearchCon ...

  9. Android游戏开发实践(1)之NDK与JNI开发04

    Android游戏开发实践(1)之NDK与JNI开发04 有了前面几篇NDK与JNI开发相关基础做铺垫,再来通过代码说明下这方面具体的操作以及一些重要的细节.那么,就继续NDK与JNI的学习总结. 作 ...

  10. jprofiler安装图解 ( 7_1 )

    环境: 1.sun jdk1.6.0 2.jprofiler_windows_6_0_2.exe 安装 1. jdk, 安装略... 2. jprofiler安装 一路next 到Enter lice ...