定时器

本文详细介绍了muduo库中定时器的实现,包括TimerId、Timer和TimerQueue三个类的作用。重点讨论了如何通过EventLoop中的runAt、runAfter和runEvery接口来设置定时器,并解释了TimerQueue数据结构选择二叉搜索树的原因。同时,提到了timerfd作为Linux提供的定时器接口,以及在处理超时事件时的流程。文章还解答了关于添加不同超时时间的定时器如何产生事件的疑惑。
摘要由CSDN通过智能技术生成

muduo的定时器由三个类实现,TimerId、Timer、TimerQueue,用户只能看到第一个类,其它两个都是内部实现细节

TimerQueue的接口很简单,只有两个函数addTimer和cancel

我们实际上在使用定时器的时候,并没有直接调用addTimer和cancel,而是调用EventLoop中的下列函数
runAt           在某个时刻运行定时器
runAfter       过一段时间运行定时器
runEvery     每隔一段时间运行定时器

cancel        取消定时器

runAt、runAfter、runEvery调用TimerQueue中的addTimer,cancel调用TimerQueue中的cancel

TimerQueue数据结构的选择,能快速根据当前时间找到已到期的定时器,也要高效的添加和删除Timer,因而可以用二叉搜索树,用map或者set,muduo中不使用map,因为这样无法处理两个Timer到期时间相同的情况。

typedef std::pair<Timestamp, Timer*> Entry;
typedef std::set<Entry> TimerList;

实际实现依靠:

timerfd是Linux为用户程序提供的一个定时器接口。这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,因此可以配合select/poll/epoll等使用。

timerfd_create()函数创建一个定时器对象,同时返回一个与之关联的文件描述符;

#include <sys/timerfd.h>

int timerfd_create(int clockid, int flags);
/* 
timerfd_create()函数创建一个定时器对象,同时返回一个与之关联的文件描述符。
clockid:clockid标识指定的时钟计数器,可选值(CLOCK_REALTIME、CLOCK_MONOTONIC。。。)
CLOCK_REALTIME:系统实时时间,随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0开始计时,中间时刻如果系统时间被用户改成其他,则对应的时间相应改变
CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
flags:参数flags(TFD_NONBLOCK(非阻塞模式)/TFD_CLOEXEC(表示当程序执行exec函数时本fd将被系统自动关闭,表示不传递)
*/

timerfd_settime()此函数用于设置新的超时时间,并开始计时,能够启动和停止定时器;

#include <sys/timerfd.h>

struct timespec {
    time_t tv_sec;                /* Seconds */
    long   tv_nsec;               /* Nanoseconds */
};

struct itimerspec {
    struct timespec it_interval;  /* Interval for periodic timer (定时间隔周期)*/
    struct timespec it_value;     /* Initial expiration (第一次超时时间)*/
};
int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
/*
    timerfd_settime()此函数用于设置新的超时时间,并开始计时,能够启动和停止定时器;
    fd: 参数fd是timerfd_create函数返回的文件句柄
    flags:参数flags为1代表设置的是绝对时间(TFD_TIMER_ABSTIME 表示绝对定时器);为0代表相对时间。
    new_value: 参数new_value指定定时器的超时时间以及超时间隔时间
    old_value: 如果old_value不为NULL, old_vlaue返回之前定时器设置的超时时间,具体参考timerfd_gettime()函数
    
    ** it_interval不为0则表示是周期性定时器。
       it_value和it_interval都为0表示停止定时器
*/

timerfd_gettime()函数获取距离下次超时剩余的时间;

#include <sys/timerfd.h>

int timerfd_create(int clockid, int flags);
/* 
timerfd_create()函数创建一个定时器对象,同时返回一个与之关联的文件描述符。
clockid:clockid标识指定的时钟计数器,可选值(CLOCK_REALTIME、CLOCK_MONOTONIC。。。)
CLOCK_REALTIME:系统实时时间,随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0开始计时,中间时刻如果系统时间被用户改成其他,则对应的时间相应改变
CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
flags:参数flags(TFD_NONBLOCK(非阻塞模式)/TFD_CLOEXEC(表示当程序执行exec函数时本fd将被系统自动关闭,表示不传递)
*/

TimerQueue维护了一系列定时器,当定时器到期后会产生一个定时器事件,Poller就会返回activeChannels,首先回调的是handleEvent(),handleEvent()又根据activeChannels是什么事件,调用TimerQueue的handleRead(),TimerQueue的handleRead()又会获取所有的超时的定时器,然后回调用户的回调函数

TimerQueue::TimerQueue(EventLo
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值