
目录一、 TimerQueue.h1. TimerQueue 的整体定位与核心设计目标2. 核心数据结构解析关键设计说明3. 核心成员变量解析4. 核心接口拆解1. 构造 / 析构初始化 timerfd 与 Channel2. 添加定时器addTimer跨线程安全3. 取消定时器cancel跨线程安全4. 内部核心方法仅 loop 线程执行5. 核心工作流程timerfd 触发时序6. 核心设计亮点总结二、 TimerQueue.cc1. 整体定位2. 4 个工具函数1. createTimerfd()2. howMuchTimeFromNow()3. readTimerfd()4. resetTimerfd()3. 构造函数 析构函数1. 构造 TimerQueue2. 析构函数4. 对外接口addTimer /cancel线程安全1. addTimer() —— 添加定时器2. cancel() —— 取消定时器5. 核心执行流程最重要6. 逐函数拆解核心逻辑1. handleRead() —— 定时器触发入口2. getExpired(now) —— 取出所有到期定时器神来之笔3. reset() —— 重置周期定时器4. insert() —— 插入定时器并判断是否更新 timerfd5. cancelInLoop() —— 取消定时器处理竞态7. 双集合设计8. 竞态安全设计9. 总结一、 TimerQueue.h先贴出完整代码再逐部分解释// Copyright 2010, Shuo Chen. All rights reserved. // http://code.google.com/p/muduo/ // // 本源代码的使用受 BSD 风格许可证约束 // 该许可证可在 License 文件中查阅。 // 作者陈硕 (chenshuo at chenshuo dot com) // // 这是一个内部头文件你不应该直接包含它。 #ifndef MUDUO_NET_TIMERQUEUE_H #define MUDUO_NET_TIMERQUEUE_H #include set #include vector #include muduo/base/Mutex.h // 互斥锁保护定时任务集合 #include muduo/base/Timestamp.h // 时间戳表示定时触发时间 #include muduo/net/Callbacks.h // 回调函数类型TimerCallback #include muduo/net/Channel.h // 管理 timerfd 的通道 namespace muduo { namespace net { class EventLoop; // 前向声明事件循环核心类 class Timer; // 前向声明定时事件封装类 class TimerId; // 前向声明定时器标识符 /// /// 定时任务队列尽力而为的定时器实现 /// 核心特性1. 基于 Linux timerfd 实现高效定时无需轮询2. 不保证回调函数严格准时执行 /// 3. 线程安全可跨线程添加/取消定时任务4. 管理所有定时任务的添加、取消、触发逻辑 /// 5. 非拷贝与单个 EventLoop 绑定 /// 注意仅保证「尽力而为」的定时精度回调执行可能因 IO 事件处理延迟而略有延后 class TimerQueue : noncopyable { public: /// 构造函数初始化定时队列核心组件 /// param loop 绑定的 EventLoop定时队列的所有操作均在该 EventLoop 线程执行 explicit TimerQueue(EventLoop* loop); /// 析构函数销毁定时队列关闭 timerfd释放所有定时任务资源 ~TimerQueue(); /// /// 添加定时任务在指定时间执行回调interval0 时重复执行 /// /// 线程安全可从任意线程调用内部会转发到 EventLoop 线程执行 /// 典型场景其他线程调用 EventLoop::runAfter/runEvery 时最终委托该方法实现 /// param cb 定时触发时执行的回调函数 /// param when 首次触发的时间戳绝对时间 /// param interval 重复间隔秒0单次定时0重复定时 /// return 定时器标识符用于取消定时任务 TimerId addTimer(TimerCallback cb, Timestamp when, double interval); /// 取消指定的定时任务 /// 线程安全可从任意线程调用内部会转发到 EventLoop 线程执行 /// param timerId 要取消的定时器标识符 void cancel(TimerId timerId); private: // FIXME 注释说明计划改用 unique_ptrTimer 替代裸指针 // 但这需要 C14 的异构比较查找N3465 标准支持 // 以实现在 setunique_ptrT 中通过 T* 查找对应元素 // 当前因兼容性保留裸指针实现 /// 定时任务集合的元素类型触发时间戳, Timer 指针 /// set 会按触发时间戳自动排序保证最早触发的任务在队首 typedef std::pairTimestamp, Timer* Entry; /// 定时任务集合按触发时间戳有序存储支持快速查找/插入/删除 typedef std::setEntry TimerList; /// 活跃定时器集合的元素类型Timer 指针, 序列号 /// 用于快速校验定时器是否有效避免野指针/重复取消 typedef std::pairTimer*, int64_t ActiveTimer; /// 活跃定时器集合存储所有未触发/未取消的定时任务 typedef std::setActiveTimer ActiveTimerSet; /// 内部方法在 EventLoop 线程添加定时任务 /// 核心约束仅能在 loop_ 所属线程调用 /// param timer 要添加的 Timer 实例指针 void addTimerInLoop(Timer* timer); /// 内部方法在 EventLoop 线程取消定时任务 /// 核心约束仅能在 loop_ 所属线程调用 /// param timerId 要取消的定时器标识符 void cancelInLoop(TimerId timerId); /// timerfd 可读事件的回调函数定时事件触发时调用 /// 执行流程1. 读取 timerfd 数据清空事件2. 获取所有已过期的定时任务 /// 3. 执行过期任务的回调4. 重置重复定时任务 void handleRead(); /// 获取所有已过期的定时任务 /// param now 当前时间戳timerfd 触发的时间 /// return 已过期的定时任务列表需执行回调 std::vectorEntry getExpired(Timestamp now); /// 重置过期的定时任务仅处理重复定时任务 /// 执行流程1. 遍历过期任务若为重复定时则重启并重新加入队列 /// 2. 非重复定时任务则释放资源 /// param expired 已过期的定时任务列表 /// param now 当前时间戳 void reset(const std::vectorEntry expired, Timestamp now); /// 插入定时任务到队列并更新 timerfd 的下一次触发时间 /// param timer 要插入的 Timer 实例指针 /// return true插入的任务是最早触发的需更新 timerfdfalse无需更新 bool insert(Timer* timer); EventLoop* loop_; // 绑定的 EventLoop所有操作均在该线程执行 const int timerfd_; // 定时触发的核心 fdLinux timerfd Channel timerfdChannel_; // 管理 timerfd 的 Channel监听读事件 TimerList timers_; // 按触发时间排序的定时任务集合核心存储 // 用于 cancel() 操作的辅助集合 ActiveTimerSet activeTimers_; // 所有活跃的定时任务未触发/未取消 bool callingExpiredTimers_; /* atomic */ // 是否正在执行过期任务的回调原子变量 ActiveTimerSet cancelingTimers_; // 正在取消的定时任务避免回调执行中取消导致的竞态 }; } // namespace net } // namespace muduo #endif // MUDUO_NET_TIMERQUEUE_H1. TimerQueue 的整体定位与核心设计目标TimerQueue是 Muduo 定时器模块的“核心管理者”为 EventLoop 提供高效的定时任务管理能力核心设计目标是高效排序与查找用红黑树std::set存储定时器按触发时间排序支持 O (logN) 时间复杂度的添加 / 删除 / 查找内核级触发基于 Linux 的timerfd实现定时器触发而非轮询与 EventLoop 的 Poller 无缝集成无额外线程开销线程安全addTimer()支持跨线程调用通过 EventLoop::runInLoop 转发cancel()处理竞态如定时器正在触发时取消周期性支持定时器触发后自动重置调用 Timer::restart重新加入队列鲁棒性通过callingExpiredTimers_等原子标记处理 “取消正在触发的定时器” 等边缘场景。在 Muduo 架构中TimerQueue 是 EventLoop 的私有成员核心关系EventLoop → 包含 TimerQueue → 管理多个 Timer → 基于 timerfd 触发 → 执行定时回调 addTimer() → 跨线程调用 → 转发到 loop 线程执行 addTimerInLoop() cancel() → 跨线程调用 → 转发到 loop 线程执行 cancelInLoop()2. 核心数据结构解析TimerQueue 的核心是两个红黑树集合std::set用于管理定时器的 “排序” 和 “快速查找取消”先理解关键类型别名类型别名定义核心作用Entrystd::pairTimestamp, Timer*定时器排序项第一元素是触发时间Timestamp第二是 Timer 指针std::set 按触发时间升序排序保证最快触发的定时器在队首TimerListstd::setEntry按触发时间排序的定时器队列核心存储结构O (logN) 查找 / 添加 / 删除保证能快速找到已过期的定时器ActiveTimerstd::pairTimer*, int64_t活跃定时器项第一元素是 Timer 指针第二是序列号Timer::sequence_用于快速查找要取消的定时器避免指针复用导致误取消ActiveTimerSetstd::setActiveTimer活跃定时器集合用于cancel()操作时快速定位定时器与 TimerList 互补关键设计说明为什么用两个集合TimerList按触发时间排序满足 “快速找过期定时器” 的需求ActiveTimerSet按 Timer* 序列号排序满足 “快速取消指定定时器” 的需求为什么不用 unique_ptr注释提到 “FIXME: use unique_ptrTimer instead of raw pointers”——C14 前不支持异构查找用 T* 查找 setunique_ptrT因此用裸指针C14 可替换为 unique_ptr 提升安全性红黑树特性std::set 底层是红黑树天然有序且插入 / 删除 / 查找的时间复杂度均为 O (logN)适合管理大量定时器。3. 核心成员变量解析成员变量类型核心作用loop_EventLoop*绑定所属的 EventLoop保证所有操作在 loop 线程执行timerfd_const intLinux timerfd 句柄内核级定时器超时后触发读事件由 Poller 监听timerfdChannel_Channel管理 timerfd_ 的 Channel注册读事件回调 handleRead ()与 EventLoop 集成timers_TimerList按触发时间排序的定时器队列核心存储activeTimers_ActiveTimerSet活跃定时器集合用于 cancel () 快速查找callingExpiredTimers_bool (atomic)原子标记是否正在处理过期定时器避免 cancel () 与触发操作竞态cancelingTimers_ActiveTimerSet取消中的定时器集合处理 “触发时取消” 的竞态临时存储待取消的定时器4. 核心接口拆解1. 构造 / 析构初始化 timerfd 与 Channelexplicit TimerQueue(EventLoop* loop); // 绑定EventLoop创建timerfd初始化Channel ~TimerQueue(); // 关闭timerfd清理所有Timer构造逻辑创建 timerfdtimerfd_create设置为非阻塞、CLOEXEC初始化 timerfdChannel_绑定 timerfd_ 和 loop_设置 Channel 的读回调为 handleRead ()启用读事件析构逻辑关闭 timerfd_清理 timers_/activeTimers_ 中的所有 Timer。2. 添加定时器addTimer跨线程安全// 线程安全可从其他线程调用最终转发到loop线程执行addTimerInLoop TimerId addTimer(TimerCallback cb, Timestamp when, double interval);核心流程新建 Timer 对象封装回调、触发时间、间隔调用 loop_-runInLoop将 addTimerInLoop (timer) 转发到 loop 线程执行返回 TimerIdTimer* 序列号给上层用于取消。3. 取消定时器cancel跨线程安全// 线程安全可从其他线程调用最终转发到loop线程执行cancelInLoop void cancel(TimerId timerId);核心目标根据 TimerId 找到对应的 Timer从 timers_/activeTimers_ 中移除处理竞态若定时器正在触发callingExpiredTimers_true则将其加入 cancelingTimers_待触发完成后清理。4. 内部核心方法仅 loop 线程执行方法核心作用addTimerInLoop(Timer* timer)实际执行添加定时器插入 timers_/activeTimers_更新 timerfd 的超时时间cancelInLoop(TimerId timerId)实际执行取消定时器查找并移除 timers_/activeTimers_ 中的对应项handleRead()timerfd 读事件回调读取 timerfd 数据清空事件获取所有过期定时器执行回调重置周期性定时器getExpired(Timestamp now)获取所有已过期的定时器now 触发时间返回 vectorEntryreset(const vectorEntry expired, Timestamp now)重置过期的周期性定时器调用 Timer::restart重新插入队列insert(Timer* timer)插入 Timer 到 timers_/activeTimers_返回是否需要更新 timerfd 超时时间5. 核心工作流程timerfd 触发时序为了更直观理解 TimerQueue 的运转梳理 “定时器触发” 的完整流程1. 上层调用 addTimer() → 插入 Timer 到 timers_ → 更新 timerfd 的超时时间为最早触发时间 2. timerfd 超时 → Poller 检测到读事件 → 触发 timerfdChannel_ 的 handleRead() 3. handleRead() 读取 timerfd 数据清空事件→ 调用 getExpired(now) 获取所有过期定时器 4. 遍历过期定时器执行 Timer::run()回调 5. 调用 reset()对周期性定时器调用 restart() 重置触发时间重新插入队列 6. 更新 timerfd 的超时时间为新的最早触发时间 7. 若有取消中的定时器cancelingTimers_清理已处理的过期定时器。6. 核心设计亮点总结设计点解决的问题工程价值基于 timerfd 触发轮询检测定时器过期效率低占用 CPU内核级触发与 Poller 无缝集成无额外线程 / 轮询开销红黑树排序std::set大量定时器的添加 / 删除 / 查找效率低O (logN) 时间复杂度支持海量定时器管理双集合TimerList/ActiveTimerSet按时间排序与快速取消需求冲突分工明确TimerList 管排序ActiveTimerSet 管取消跨线程安全runInLoop定时器操作跨线程导致竞态所有核心操作转发到 loop 线程执行保证线程安全竞态处理callingExpiredTimers_取消正在触发的定时器导致崩溃原子标记 临时队列安全处理 “触发中取消” 的边缘场景周期性定时器重置周期性定时需要手动重新添加使用复杂自动重置触发时间重新插入队列简化上层使用二、 TimerQueue.cc先贴出完整代码再逐部分解释// Copyright 2010, Shuo Chen. All rights reserved. // http://code.google.com/p/muduo/ // // 本源代码使用 BSD 许可证 // 可在 License 文件中找到详细条款 // 作者陈硕 (chenshuo at chenshuo dot com) // 定义 STDC_LIMIT_MACROS 以使用 UINTPTR_MAX #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif #include muduo/net/TimerQueue.h #include muduo/base/Logging.h #include muduo/net/EventLoop.h #include muduo/net/Timer.h #include muduo/net/TimerId.h #include sys/timerfd.h #include unistd.h namespace muduo { namespace net { // 匿名细节命名空间内部工具函数对外不可见 namespace detail { /// 创建 timerfd 文件描述符 /// 使用 CLOCK_MONOTONIC 单调时钟非阻塞、exec 时自动关闭 int createTimerfd() { int timerfd ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); if (timerfd 0) { LOG_SYSFATAL timerfd_create 创建失败; } return timerfd; } /// 计算目标时间戳距离当前时间的时长返回 timespec 结构 /// 最小间隔 100 微秒避免立即触发导致的问题 struct timespec howMuchTimeFromNow(Timestamp when) { int64_t microseconds when.microSecondsSinceEpoch() - Timestamp::now().microSecondsSinceEpoch(); if (microseconds 100) { microseconds 100; } struct timespec ts; ts.tv_sec static_casttime_t( microseconds / Timestamp::kMicroSecondsPerSecond); ts.tv_nsec static_castlong( (microseconds % Timestamp::kMicroSecondsPerSecond) * 1000); return ts; } /// 读取 timerfd清空触发事件 /// timerfd 触发后必须读取否则会一直触发 void readTimerfd(int timerfd, Timestamp now) { uint64_t howmany; ssize_t n ::read(timerfd, howmany, sizeof howmany); LOG_TRACE TimerQueue::handleRead() 触发次数 howmany 时间 now.toString(); if (n ! sizeof howmany) { LOG_ERROR TimerQueue::handleRead() 读取字节数错误 n 应读取 8 字节; } } /// 重新设置 timerfd 的超时时间 /// 让内核在指定时间触发 timerfd 读事件 void resetTimerfd(int timerfd, Timestamp expiration) { struct itimerspec newValue; struct itimerspec oldValue; memZero(newValue, sizeof newValue); memZero(oldValue, sizeof oldValue); newValue.it_value howMuchTimeFromNow(expiration); int ret ::timerfd_settime(timerfd, 0, newValue, oldValue); if (ret) { LOG_SYSERR timerfd_settime() 设置失败; } } } // namespace detail } // namespace net } // namespace muduo using namespace muduo; using namespace muduo::net; using namespace muduo::net::detail; /// 构造函数创建 timerfd绑定 Channel TimerQueue::TimerQueue(EventLoop* loop) : loop_(loop), // 所属 EventLoop timerfd_(createTimerfd()), // 创建 timerfd timerfdChannel_(loop, timerfd_), // 用 Channel 管理 timerfd timers_(), // 定时任务有序集合 callingExpiredTimers_(false) // 未在执行超时回调 { // 设置 timerfd 可读时的回调函数 timerfdChannel_.setReadCallback( std::bind(TimerQueue::handleRead, this)); // 关注 timerfd 的读事件 timerfdChannel_.enableReading(); } /// 析构函数关闭 timerfd释放所有定时器对象 TimerQueue::~TimerQueue() { timerfdChannel_.disableAll(); timerfdChannel_.remove(); ::close(timerfd_); // 删除所有定时器对象 for (const Entry timer : timers_) { delete timer.second; } } /// 添加定时器线程安全 /// 会把任务投递到 IO 线程执行 TimerId TimerQueue::addTimer(TimerCallback cb, Timestamp when, double interval) { // 创建定时器对象 Timer* timer new Timer(std::move(cb), when, interval); // 投递到 IO 线程执行添加 loop_-runInLoop( std::bind(TimerQueue::addTimerInLoop, this, timer)); // 返回定时器 ID用于取消 return TimerId(timer, timer-sequence()); } /// 取消定时器线程安全 /// 投递到 IO 线程执行取消 void TimerQueue::cancel(TimerId timerId) { loop_-runInLoop( std::bind(TimerQueue::cancelInLoop, this, timerId)); } /// IO 线程内真正执行添加定时器 void TimerQueue::addTimerInLoop(Timer* timer) { loop_-assertInLoopThread(); // 插入定时器并判断是否改变了最早超时时间 bool earliestChanged insert(timer); // 如果最早超时时间改变需要重新设置 timerfd if (earliestChanged) { resetTimerfd(timerfd_, timer-expiration()); } } /// IO 线程内真正执行取消定时器 void TimerQueue::cancelInLoop(TimerId timerId) { loop_-assertInLoopThread(); assert(timers_.size() activeTimers_.size()); // 构造要取消的定时器键Timer* 序列号 ActiveTimer timer(timerId.timer_, timerId.sequence_); ActiveTimerSet::iterator it activeTimers_.find(timer); // 找到则直接删除 if (it ! activeTimers_.end()) { size_t n timers_.erase(Entry(it-first-expiration(), it-first)); assert(n 1); (void)n; delete it-first; activeTimers_.erase(it); } // 如果正在执行回调先加入待取消集合避免迭代器失效 else if (callingExpiredTimers_) { cancelingTimers_.insert(timer); } assert(timers_.size() activeTimers_.size()); } /// timerfd 超时触发的读事件回调 void TimerQueue::handleRead() { loop_-assertInLoopThread(); Timestamp now(Timestamp::now()); // 读取 timerfd清空事件 readTimerfd(timerfd_, now); // 获取所有已超时的定时器 std::vectorEntry expired getExpired(now); // 标记正在执行超时回调 callingExpiredTimers_ true; cancelingTimers_.clear(); // 执行所有超时定时器的回调 for (const Entry it : expired) { it.second-run(); } // 结束执行回调 callingExpiredTimers_ false; // 重置重复定时器清理单次定时器 reset(expired, now); } /// 获取所有已超时的定时器并从队列中移除 std::vectorTimerQueue::Entry TimerQueue::getExpired(Timestamp now) { assert(timers_.size() activeTimers_.size()); std::vectorEntry expired; // 哨兵值找到所有 当前时间的定时器 Entry sentry(now, reinterpret_castTimer*(UINTPTR_MAX)); TimerList::iterator end timers_.lower_bound(sentry); // 复制所有超时定时器 std::copy(timers_.begin(), end, back_inserter(expired)); // 从定时器队列中删除 timers_.erase(timers_.begin(), end); // 从活跃定时器集合中删除 for (const Entry it : expired) { ActiveTimer timer(it.second, it.second-sequence()); size_t n activeTimers_.erase(timer); assert(n 1); (void)n; } assert(timers_.size() activeTimers_.size()); return expired; } /// 重置超时的定时器 /// 重复定时器重新插入单次定时器释放 void TimerQueue::reset(const std::vectorEntry expired, Timestamp now) { Timestamp nextExpire; for (const Entry it : expired) { ActiveTimer timer(it.second, it.second-sequence()); // 如果是重复定时器且未被取消则重启 if (it.second-repeat() cancelingTimers_.find(timer) cancelingTimers_.end()) { it.second-restart(now); insert(it.second); } else { // 单次定时器或已取消直接释放 delete it.second; } } // 如果还有定时器设置下一次超时时间 if (!timers_.empty()) { nextExpire timers_.begin()-second-expiration(); } if (nextExpire.valid()) { resetTimerfd(timerfd_, nextExpire); } } /// 插入定时器到有序集合 /// 返回是否改变了最早的超时时间 bool TimerQueue::insert(Timer* timer) { loop_-assertInLoopThread(); assert(timers_.size() activeTimers_.size()); bool earliestChanged false; Timestamp when timer-expiration(); TimerList::iterator it timers_.begin(); // 如果队列为空 或 新定时器更早则更新最早时间 if (it timers_.end() || when it-first) { earliestChanged true; } // 插入到有序定时器集合 { std::pairTimerList::iterator, bool result timers_.insert(Entry(when, timer)); assert(result.second); (void)result; } // 插入到活跃定时器集合 { std::pairActiveTimerSet::iterator, bool result activeTimers_.insert(ActiveTimer(timer, timer-sequence())); assert(result.second); (void)result; } assert(timers_.size() activeTimers_.size()); return earliestChanged; }1. 整体定位TimerQueue是EventLoop 内部的定时器管理器用timerfd把 “定时” 变成 IO 事件和 Reactor 无缝融合用std::set红黑树按到期时间排序定时器快速取到期任务提供线程安全的addTimer/cancel自动处理单次 / 周期定时器解决 “回调中取消定时器” 的竞态问题。2. 4 个工具函数这 4 个函数封装timerfd系统调用是定时器的地基。1.createTimerfd()创建 Linux 内核定时器文件描述符int timerfd ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);CLOCK_MONOTONIC绝对时间不会回退比 REALTIME 安全TFD_NONBLOCK非阻塞TFD_CLOEXECfork 后自动关闭避免 fd 泄漏。2. howMuchTimeFromNow()计算 “从现在到定时器到期” 还剩多久返回timespec。小于 100us 强制设为 100us避免频繁触发。3. readTimerfd()timerfd 触发时必须read一下否则会一直触发事件。读出的uint64_t是触发次数。4. resetTimerfd()设置 timerfd 下次超时时间timerfd_settime(timerfd, 0, newValue, oldValue);这是真正让定时器跑起来的系统调用。3. 构造函数 析构函数1. 构造TimerQueueTimerQueue::TimerQueue(EventLoop* loop) : loop_(loop), timerfd_(createTimerfd()), timerfdChannel_(loop, timerfd_), callingExpiredTimers_(false) { // 绑定读回调timerfd 超时 → 调用 handleRead() timerfdChannel_.setReadCallback(std::bind(TimerQueue::handleRead, this)); timerfdChannel_.enableReading(); // 监听读事件 }核心timerfd Channel 把定时器变成可读事件完全融入 Reactor。不需要额外线程不需要轮询。2. 析构函数关闭 channel、关闭 timerfddelete 所有 Timer 对象裸指针管理。4. 对外接口addTimer /cancel线程安全1.addTimer()—— 添加定时器TimerId TimerQueue::addTimer(...) { Timer* timer new Timer(...); loop_-runInLoop(std::bind(TimerQueue::addTimerInLoop, this, timer)); return TimerId(timer, timer-sequence()); }关键点无论哪个线程调用最终都在IO 线程执行返回TimerIdTimer* 序列号给用户用于取消。2.cancel()—— 取消定时器void cancel(TimerId timerId) { loop_-runInLoop(std::bind(TimerQueue::cancelInLoop, this, timerId)); }同样必须在 IO 线程执行。5. 核心执行流程最重要完整触发链路timerfd 超时 → Poller 返回 → Channel 读回调 → handleRead() → 取出所有到期定时器 → 执行回调 → 重置周期定时器 → 更新 timerfd6. 逐函数拆解核心逻辑1.handleRead()—— 定时器触发入口void TimerQueue::handleRead() { Timestamp now Timestamp::now(); readTimerfd(timerfd_, now); // 必须读清空事件 auto expired getExpired(now); // 取出所有到期定时器 callingExpiredTimers_ true; for (auto e : expired) { e.second-run(); // 执行用户回调 } callingExpiredTimers_ false; reset(expired, now); // 重置周期定时器 }这是定时器的 “心跳”。2.getExpired(now)—— 取出所有到期定时器神来之笔Entry sentry(now, (Timer*)UINTPTR_MAX); auto end timers_.lower_bound(sentry);timers_是setpairTimestamp, Timer*按时间升序lower_bound(sentry)找到第一个未到期的迭代器[begin, end)全是已到期定时器。然后从timers_删掉从activeTimers_删掉返回给handleRead执行。3.reset()—— 重置周期定时器if (it.second-repeat() 不在取消列表) { it.second-restart(now); insert(it.second); } else { delete it.second; }周期定时器restart()计算下次时间重新插入队列单次定时器直接 delete最后更新timerfd为最早到期时间。4.insert()—— 插入定时器并判断是否更新 timerfdbool earliestChanged (新定时器是队列最早) ? true : false;如果新定时器是最早要触发的必须重新设置timerfd。同时插入两个集合timers_按时间排序activeTimers_按Timer*seq排序用于快速取消。5.cancelInLoop()—— 取消定时器处理竞态if (找到) 删定时器 delete else if (正在执行回调) 放进 cancelingTimers_ 待删解决经典问题回调执行过程中取消自己。7. 双集合设计setEntry timers_; // 按时间排序用于取到期 setActiveTimer activeTimers_; // 按Timer*seq排序用于取消timers_快速找到期定时器O (logN)activeTimers_快速根据 TimerId 找到定时器O (logN)两个集合大小永远相等代码里大量assert校验。8. 竞态安全设计callingExpiredTimers_ cancelingTimers_作用用户在定时器回调里调用 cancel () 不会崩溃、不会重复析构。9. 总结TimerQueue timerfd Channel 红黑树完全融入 Reactor所有操作必须在 IO 线程执行保证线程安全std::set按时间排序取到期定时器是O(logN)周期定时器自动restart无需用户干预TimerId用Timer 序列号* 唯一标识安全取消完美处理回调中取消定时器的竞态。