muduo源代码分析--Reactor模式在muduo中的使用
一. Reactor模式简单介绍
Reactor释义"反应堆",是一种事件驱动机制。和普通函数调用的不同之处在于:应用程序不是主动的调用某个API完毕处理。而是恰恰相反。Reactor逆置了事件处理流程,应用程序须要提供对应的接口并注冊到Reactor上,假设对应的时间发生,Reactor将主动调用应用程序注冊的接口,这些接口又称为"回调函数"。
二. moduo库Reactor模式的实现
muduo主要通过3个类来实现Reactor模式:EventLoop,Channel。Poller。
1. EventLoop
事件循环。
moduo的线程模型为one loop per thread,即每一个线程仅仅能有一个EventLoop对象。
EventLoop对象的生命周期通常和其所属的线程一样长。
数据成员:
const pid_t threadId_;保存当前EventLoop所属线程id
boost::scoped_ptr poller_; 实现I/O复用 boost::scoped_ptr timerQueue_;
int wakeupFd_;
boost::scoped_ptr wakeupChannel_; 用于处理wakeupFd_上的可读事件。将事件分发到handlRead() ChannelList activeChannels_; 有事件就绪的 Channel Channel* currentActiveChannel_;
MutexLock mutex_; pendingFunctors_回暴露给其它线程,所以须要加锁 std::vectorpendingFunctors_;
主要功能函数:
loop(),在该函数中会循环运行下面过程:调用Poller::poll()。通过此调用获得一个vectoractiveChannels_的就绪事件集合,再遍历该容器,运行每一个Channel的Channel::handleEvent()完毕对应就绪事件回调,最后运行pendingFunctors_排队的函数。上述一次循环就是一次Reactor模式完毕。
runInLoop(boost::function),实现用户指定任务回调,若是EventLoop隶属的线程调用EventLoop::runInLoop()则EventLoop立即运行;若是其他线程调用则运行EventLoop::queueInLoop(boost::function将任务加入到队列中(线程转移)。EventLoop怎样获得有任务这一事实呢?通过eventfd能够实现线程间通信。详细做法是:其他线程向EventLoop::vector >加入任务T,然后通过EventLoop::wakeup()向eventfd写一个int,eventfd的回调函数EventLoop::handleRead()读取这个int。从而相当于EventLoop被唤醒,此时loop中遍历队列运行堆积的任务。这里採用Channel管理eventfd。Poller侦听eventfd体现了eventfd能够统一事件源的优势。
queueInLoop(Functor& cb),将cb放入队列,并在必要时唤醒IO线程。有两种情况须要唤醒IO线程,1 调用queueInLoop()的线程不是IO线程,2 调用queueInLoop()的线程是IO线程,而此时正在调用pengding functor。
2. Channel
事件分发器。每一个Channel仅仅属于一个EventLoop,每一个Channel仅仅负责一个文件描写叙述符fd的IO事件分发。但其不拥有fd。
数据成员:
int fd_文件描写叙述符,
int events_ 文件描写叙述符注冊事件。
int revents_文件描写叙述符的就绪事件,由Poller::poll设置
readCallback_,writeCallback...各种事件回调。会在拥有该Channel类的构造函数中被注冊,比如TcpConnction会在构造函数中TcpConnection::handlRead()注冊给Channel::readCallback
主要功能函数:
setCallback()系列函数,接受Channel所属的类注冊对应的事件回调函数
enableReading(),update(), 当一个fd想要注冊可读事件时,首先通过Channel::enableReading()-->Channel::update(this)->EventLoop::updateChannel(Channel)->Poller::updateChannel(Channel*)调用链向poll系统调用的侦听事件表注冊或者改动注冊事件。
handleEvent(), Channel作为是事件分发器其核心结构是Channel::handleEvent(),该函数调用Channel::handleEventWithGuard(),在其内依据Channel::revents的值分发调用对应的事件回调。
3. Poller
Poller是IO multiplexing的封装。封装了poll和epoll。
Poller是EventLoop的间接成员。仅仅供拥有该Poller的EventLoop在IO线程调用。生命期与EventLoop相等。
数据成员:
vector pollfds_事件结构体数组用于poll的第一个參数;
map channels_用于文件描写叙述符fd到Channel的映射便于高速查找到对应的Channel
主要功能函数:
updateChannel(Channel*) 用于将传入的Channel关心的事件注冊给Poller。
poll(int timeoutMs,vector activeChannels)其调用poll侦听事件集合,将就绪事件所属的Channel调用fillActiveChannels()增加到activeChannels_中。
其它类
EventLoopThread: 启动一个线程运行一个EventLoop,其语义和"one loop per thread"相吻合。注意这里用到了相互排斥量和条件变量,这是由于线程A创建一个EventLoopThread对象后一个运行EventLoop的线程已经開始创建了。能够通过EventLoopThread::startLoop()获取这个EventLoop对象。可是若EventLoop线程还没有创建好。则会出错。
所以在创建EventLoop完毕后会运行condititon.notify()通知线程A,线程A调用EventLoopThread::startLoop()时调用condition.wai()等待,从而保证获取一个创建完毕的EventLoop.毕竟线程A创建的EventLoop线程,A可能还会调用EventLoop运行一些任务回调呢。
muduo源代码分析--Reactor模式在muduo中的使用的更多相关文章
- muduo源代码分析--Reactor在模型muduo使用(两)
一. TcpServer分类: 管理所有的TCP客户连接,TcpServer对于用户直接使用,直接控制由用户生活. 用户只需要设置相应的回调函数(消息处理messageCallback)然后TcpSe ...
- Reactor 模式在Netty中的应用
Reactor 模式在Netty中的应用 典型的Rector模式 mainReactor 服务端创建成功后,会监听Accept操作,其中ServerSocketchannel中的PipeLine中现在 ...
- muduo源代码分析--我对muduo的理解
分为几个模块 EventLoop.TcpServer.Acceptor.TcpConnection.Channel等 对于EventLoop来说: 他仅仅关注里面的主驱动力,EventLoop中仅仅关 ...
- Reactor模式解析——muduo网络库
最近一段时间阅读了muduo源码,读完的感受有一个感受就是有点乱.当然不是说代码乱,是我可能还没有完全消化和理解.为了更好的学习这个库,还是要来写一些东西促进一下. 我一边读一边尝试在一些地方改用c+ ...
- 公布一个基于 Reactor 模式的 C++ 网络库
公布一个基于 Reactor 模式的 C++ 网络库 陈硕 (giantchen_AT_gmail) Blog.csdn.net/Solstice 2010 Aug 30 本文主要介绍 muduo 网 ...
- Reactor模式详解
转自:http://www.blogjava.net/DLevin/archive/2015/09/02/427045.html 前记 第一次听到Reactor模式是三年前的某个晚上,一个室友突然跑过 ...
- Hadoop源代码分析
http://wenku.baidu.com/link?url=R-QoZXhc918qoO0BX6eXI9_uPU75whF62vFFUBIR-7c5XAYUVxDRX5Rs6QZR9hrBnUdM ...
- 转一篇:Reactor模式
转载自:http://www.blogjava.net/DLevin/archive/2015/09/02/427045.html 前记 第一次听到Reactor模式是三年前的某个晚上,一个室友突然跑 ...
- (转)reactor模式
转自: http://www.blogjava.net/DLevin/archive/2015/09/02/427045.html Reactor模式详解 前记 第一次听到Reactor模式是三年前的 ...
随机推荐
- C#中练级orcle数据查询
直接贴代码哈哈哈, public DataTable getInfo(int flag) { OracleConnection conn = null; DataSet ds = new DataSe ...
- MySQL 中去重 distinct 用法
在使用MySQL时,有时需要查询出某个字段不重复的记录,这时可以使用mysql提供的distinct这个关键字来过滤重复的记录,但是实际中我们往往用distinct来返回不重复字段的条数(count( ...
- Perl字符集[\d\D]表示任何字符(所有数字和非数字,包括换行符),“.”表示除了换行符以外的所有字符。
Perl字符集[\d\D]表示任何字符(所有数字和非数字,包括换行符),“.”表示除了换行符以外的所有字符.
- 第2节 mapreduce深入学习:9、手机上行流量排序
还是上次那个例子,需求二:上行流量倒序排序(递减排序) 分析,以需求一的输出数据作为排序的输入数据,自定义FlowBean,以FlowBean为map输出的key,以手机号作为Map输出的value, ...
- torch.nn.Embedding理解
Pytorch官网的解释是:一个保存了固定字典和大小的简单查找表.这个模块常用来保存词嵌入和用下标检索它们.模块的输入是一个下标的列表,输出是对应的词嵌入. torch.nn.Embedding(nu ...
- IO之DataStream数据流举例
import java.io.*; public class TestDataStream { public static void main(String[] args) { ByteArrayOu ...
- [Python3网络爬虫开发实战] 2.3-爬虫的基本原理
我们可以把互联网比作一张大网,而爬虫(即网络爬虫)便是在网上爬行的蜘蛛.把网的节点比作一个个网页,爬虫爬到这就相当于访问了该页面,获取了其信息.可以把节点间的连线比作网页与网页之间的链接关系,这样蜘蛛 ...
- 【memcached】memcached中flags字段的作用
我们一般只注意到memcached的数据结构是key,value,今天看memcached源代码的时候,盯上了flags,没看明白.后来问了一下同事,说PHP当中使用flags标记,标识memcach ...
- PHP实现微信第三方登录的方法
本文实例讲述了PHP版微信第三方实现一键登录及获取用户信息的方法.分享给大家供大家参考,具体如下: 注意,要使用微信在第三方网页登录是需要“服务号”才可以哦,所以必须到官方申请 一开始你需要进入微信公 ...
- mysql You can't specify target table 'sys_org_relation' for update in FROM clause 删除表条件不能直接包含该表
mysql中You can't specify target table for update in FROM clause错误的意思是说,不能先select出同一表中的某些值,再update这个表( ...