Eventloop中维护了一个定时器队列:
boost::scoped_ptr<TimerQueue> timerQueue_;
在事件循环中的所有定时器事件都会被放入到这个”队列”中,当然本质上是放在一棵平衡二叉树中(muti-set)。放置定时器的相关函数主要是是Eventloop中的下列成员函数:
TimerId runAt(const Timestamp& time, const TimerCallback& cb); //在时间点time调用cb
TimerId runAfter(double delay, const TimerCallback& cb);//过delay的时间后调用cb
TimerId runEvery(double interval, const TimerCallback& cb);//每隔internal的时间调用一次cb
三个函数都包含两个参数,一个是时间相关的参数,一个是回调函数。都表示在某个时间(粗略)到达后,调用相应的回调函数。从它们的源码可以看出,核心是调用timerQueue_的成员函数addTimer:
timerQueue_->addTimer(cb, time, 0.0);
下面我们看一下timerQuene的实现:
TimesQuene的核心数据成员是:
const int timerfd_;
TimerList timers_;
其中timers_是一个multiset(平衡二叉树),树中的元素是Timer,Timer是定时器对象。它封装了定时器相关的事件和回调函数。timerfd_是一个文件描述符,它通过timerfd_create创建。timefd_是linux中的一种机制,通过它可以将定时器事件和IO事件统一管理。因此我们可以像普通的文件描述符一样将timefd加入到epoll中,不过它的事件触发机制和普通的文件描述符不同,它是到达一定的设置时间后就会触发一个事件,时间可以由timerfd_settime库函数进行设置。因此会想到,对TimerQuene