看了国人写的一个C++开源网络库,写点小结吧。
代码版本:muduo-0.9.7-beta
1. EventLoop
一个线程只能有一个Eventloop实例,通过_thread变量检测。
EventLoop内部是while循环事件检测触发器,poller可以是poll或者epoll两种。
EventLoop处理 socketfd,eventfd,和timerfd三种。
a. eventfd
当投递事件到EventLoop中执行时,需要唤醒线程,通过write eventfd唤醒。
两种情况下需要唤醒EventLoop:
1. 从其他线程投递functor
2. 已经是在本线程中,并且是在执行pending functor过程中又投递新的functor(在eventloop执行过程中,新产生的pending functor是没有机会执行到的,所以需要再次唤醒)
b. socketfd
socketfd是和TcpConnection关联一起的,网络数据收发处理。
c. timerfd
timerfd和timerqueue关联,实现定时器事件。
2. TimerQueue
定时器包装在了TimerQueue类,作为EventLoop的成员
以下两个set其实元素都是timers对象
TimerList 使用了expired time作为key,这样可以方便得到当前超时的timer(s)对象。
ActiveTimerSet 使用timer对象作为可以,方便索引删除定时器。
TimerList timers_;
ActiveTimerSet cancelingTimers_;
删除定时器逻辑:
1. 如果在ActiveTimerSet 中,表示当前定时器还未超时,直接从上面两个set中予以删除。
2. 如果是在定时器回调函数中删除定时器,那么先保存到cancelingTimers_ set中,等待本次超时所有timers回调函数执行完毕,这时候删除的只能是循环定时器,不会有下次超时了。
3. EventloopThreadPool
Eventloop
EventloopThread
EventloopThreadPool
三者关系:一层层包含。
一般情况下,main主线程有一个Eventloop,如果一个eventloop要处理的事件太多,那么可以根据需要开启Eventloop线程池,将不同的事件(各种fd产生的)分散到多个线程中,这样可以提高IO效率。
EventloopThreadPool初始化需要一个主Eventloop。
EventloopThread新建线程,返回Eventloop实例,由EventloopThreadPool来管理。
4. Channel
Channel(EventLoop* loop, int fd);
从channel的构造函数就可以知道,该类将各种fd和EventLoop关联起来的。
事件处理类(比如TcpConnection),向channel注册需要关心的事件,并且通过boost::bind绑定事件的处理函数。
随后poller检测事件发生,通过channel就能找到该事件(socket readable,writeable等)对应的处理函数,这就是reactor模型。