muduo 的定时器功能由三个 class 实现,TimerId、Timer 和 TimerQueue。
TimerId 类
它唯一标识一个 Timer 定时器。TimerId Class 同时保存Timer* 和 sequence_,这个 sequence_ 是每个 Timer 对象有一个全局递增的序列号 int64_t sequence_,用原子计数器(AtomicInt64)生成。
它主要用于注销定时器,这样就可以区分地址相同的先后两个 Timer 对象。
namespace muduo
{
namespace net
{
class Timer;
///
/// An opaque identifier, for canceling Timer.
///
/* 带有唯一标识的Timer,主要用于取消Timer */
class TimerId : public muduo::copyable
{
public:
TimerId()
: timer_(NULL),
sequence_(0)
{
}
TimerId(Timer* timer, int64_t seq)
: timer_(timer), //timer 定时器的指针
sequence_(seq) //seq 该定时任务的序列号
{
}
// default copy-ctor, dtor and assignment are okay
friend class TimerQueue;
private:
Timer* timer_;
int64_t sequence_;
};
}
}
Timer 类
封装了定时器的一些参数,包括超时时间(expiration_)、超时回调函数(callback_)、时间间隔(interval_)、是否重复定时(repeat_)、定时器的序列号等成员变量,成员函数大都是返回这些变量的值,run() 用来调用回调函数,restart() 用来重启定时器。
Timer.h
namespace muduo
{
namespace net
{
///
/// Internal class for timer event.
///
/* 定时器 */
class Timer : boost::noncopyable
{
public:
Timer(const TimerCallback& cb, Timestamp when, double interval)
: callback_(cb),
expiration_(when),
interval_(interval),
repeat_(interval > 0.0),
sequence_(s_numCreated_.incrementAndGet())
{ }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
Timer(TimerCallback&& cb, Timestamp when, double interval)
: callback_(std::move(cb)),
expiration_(when),
interval_(interval),
repeat_(interval > 0.0),
sequence_(s_numCreated_.incrementAndGet())
{ }
#endif
void run() const
{
callback_(); //执行定时器回调函数
}
/* 返回定时器的超时时间戳 */
Timestamp expiration() const { return expiration_; }
/* 是否周期性定时 */
bool repeat() const { return repeat_; }
/* 返回本定时器的序列号 */
int64_t sequence() const { return sequence_; }
/* 重启定时器 */
void restart(Timestamp now);
static int64_t numCreated() { return s_numCreated_.get(); }
private:
const TimerCallback callback_; //超时回调函数
Timestamp expiration_; //超时时间戳
const double interval_; //时间间隔,如果是一次性定时器,该值为0
const bool repeat_; //是否重复执行
const int64_t sequence_; //本定时任务的序号
static AtomicInt64 s_numCreated_; //定时器计数,当前已经创建的定时器数量
};
}
}
Timer.cc
#include <muduo/net/Timer.h>
using namespace muduo;
using namespace muduo::net;
AtomicInt64 Timer::s_numCreated_;
void Timer::restart(Timestamp now)
{
if (repeat_)
{
//如果需要重复,那就将时间设为下次超时的时间
expiration_ = addTime(now, interval_);
}
else
{
//如果不需要重复,那就将超时时间设为一个不可用的 value
expiration_ = Timestamp::invalid();
}
}
TimerQueue 类
定时器队列,用于管理所有的定时器,此类的接口只有两个:添加和注销定时器,分别为 addTimer()
和 cancel()
。
TimerQueue 数据结构的选择。需要高效地组织目前尚未到期的 Timer,能快速地根据当前时间找到已经到