这里所涉及的文件包括
(1)loop用的:Callbacks,Poller,EventLoop,EventLoopThread,EventLoopThreadPool
(2)IO用的:Channel
(3)Timer用的:Timer,TimerQueue,TimerId
1.与Libev对比
可以用于libev的对比来很好滴表达
(1)Poller+EventLoop实现了libev的loop循环
(2)Channel就是libev的io_watcher
(3)TimerQueue就是libev的timer_watcher(但是注意muduo中有N多个定时事件,也只是有一个timer_watcher)
这样对应以后,功能也就是一目了然。
2.程序的组织
如图所示,一个线程持有一个loop
一个loop通过一个poller来实现IO multiplexing
有前面可知,Channel的作用相当于watcher,IO事件以及Timer事件都是通过文件描述符,注册一个Channel来操作的。
注意:
(1)各个fd
一个channel/watcher只能对应一个fd。
①listenfd只有一个用于服务器接受连接请求,并为新的connection建立监听
②connfd可以有若干个,所以就会建立对应那么多个channel
③timerfd,这里TimerQueue里面可以有很多个timer,每一个timer代表一个时间事件。
但是整个TimerQueue在Poller中只对应一个channel。
(2)详细解释timer相关
有关对于时间处理的简单示例代码可以参考muduo/net/tests/Channel_test.cc
IO的fd都是一个fd对应一个channel,每个channel的callback都是对应于那个时间的处理
而包含有许多timer的TimerQueue只有一个fd,当在这个fd的事件到达,会调用TimerQueue::handleRead作为CallBack。
在handleRead中,再将TimerQueue中的这个时候超时的所有的timer的callback一一调用。
①代表整个TimerQueue的timerfd是在构造的时候调用timerfd_create创建的
并且还要通过用这个timerfd创建一个Channel,并且将这个channel设置为关注read事件,并加入poller的监听队列。
②目前的TimerQueue是空的,可以往里面加入timer(timer由when,cb组成,表示用户关心的一个时间发生的事件,以及发生后的callback)。
调用的顺序为add_timer----->addTimerInLoop-------->insert------------>判断是否调用resetTimerfd
这里的insert就是实际将timer插入底层数据结构的函数
关键就是这里的判断,它是判断当前新插入的这个timer是否比已经在队列中的所有timer的when的最前面(即?when_now<when_min)。
如果是就通过resetTimerfd在底层调用timerfd_settime,而这个函数的功能就是设定代表整个TimerQueue的channel关注的那个事件准备就绪的条件。
说穿了就是在用户所有关心的时间事件里面,将最先发生的那个作为Poller通知timerchannel事件发生(timerfd变为可读)的标志,
当定时发生,callback就调用handleRead。
这个handleRead再反过来调用这个时候到时的各个Timer的各自的callback。
3.类的数据成员包含关系
为了进行逻辑判断,一个类里面本身有很多数据成员,但是我在这里忽略一些循环变量,用于指示的布尔变量。
只关心muduo库的类的对象作为数据成员
(1)EventLoop
①poller
②timerQueue
③wakeupChannel
④activeChannels(vector)
(2)Poller
①ownerLoop
②channels(map<int, Channel>即map<fd, Channel>)
③pollfds(vector<struct pollfd> stated in pollpoller.h)
(3)Channel
①loop
②fd,events,revents
③read,write,close,error四种Callback(boost::function<>)
(4)TimerQueue
①loop
②timerfd
③timerfdChannel
④timers(set<pair<Timerstamp, Timer*>>)
(5)Timer
①callback(boost::function<> defined in Callbacks.h)
②expiration(Timerstamp)
③interval(double)