|
@@ -7,10 +7,20 @@
|
|
|
#include <vector>
|
|
|
#include <iostream>
|
|
|
|
|
|
+/**
|
|
|
+ * @brief 这是一个时间轮定时器的实现,将任务添加到时间轮中,时间轮会在指定的时间点执行任务
|
|
|
+ * 任务是一个函数对象,可以是lambda表达式,也可以是std::bind绑定的函数
|
|
|
+ * 任务是挂在一个个时间点上的,同一个时间点可以有多个任务,时间点的最大数目就是任务容器最大容量
|
|
|
+ *
|
|
|
+ * 缺点:
|
|
|
+ * 1、时间轮的时间点是固定的,如果任务的时间点不在时间轮的时间点上,就会被延迟执行
|
|
|
+ * 2、任务执行是在这个线程中执行的,如果任务执行时间过长,会影响时间轮的执行
|
|
|
+ */
|
|
|
+
|
|
|
class TimerWheel {
|
|
|
public:
|
|
|
using Task = std::function<void()>;
|
|
|
-
|
|
|
+ /* 构造函数,第一个参数是任务时间点容器最大数量,第二个参数是最低检测时间单位 */
|
|
|
explicit TimerWheel(size_t wheel_size, int interval_ms)
|
|
|
: wheel_size_(wheel_size),
|
|
|
interval_ms_(interval_ms),
|
|
@@ -20,12 +30,13 @@ public:
|
|
|
~TimerWheel() {
|
|
|
Stop();
|
|
|
}
|
|
|
-
|
|
|
+ /* 开启时间轮 */
|
|
|
void Start() {
|
|
|
if (running_) {
|
|
|
return;
|
|
|
}
|
|
|
running_ = true;
|
|
|
+ /* 开启新线程,定时检测队列 */
|
|
|
thread_ = std::thread([this]() {
|
|
|
while (running_) {
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(interval_ms_));
|
|
@@ -45,11 +56,14 @@ public:
|
|
|
thread_.join();
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+ /* 添加任务函数 */
|
|
|
void AddTask(int timeout_ms, Task task) {
|
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
|
+ /* 计算出需要轮训的次数 */
|
|
|
size_t ticks = timeout_ms / interval_ms_;
|
|
|
+ /* 在当前时间点上加上ticks */
|
|
|
size_t index = (current_index_ + ticks) % wheel_size_;
|
|
|
+ /* 这里是设置在整个时间轮中,该任务在这个时间轮中的分布,以实现循环定时 */
|
|
|
size_t allindex = index;
|
|
|
for (size_t i = 1 ; allindex < wheel_size_; i++)
|
|
|
{
|
|
@@ -62,21 +76,24 @@ public:
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
+ /* 时间片 */
|
|
|
void Tick() {
|
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
|
+ /* 取出这个时间点的函数,循环执行 */
|
|
|
auto& tasks = wheel_[current_index_];
|
|
|
for (const auto& task : tasks) {
|
|
|
task();
|
|
|
}
|
|
|
//tasks.clear();
|
|
|
+ /* 可以循环定时的关键,超过了设置的最大时间点,就会重置 */
|
|
|
current_index_ = (current_index_ + 1) % wheel_size_;
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
- size_t wheel_size_;
|
|
|
- int interval_ms_;
|
|
|
- std::vector<std::list<Task>> wheel_;
|
|
|
- size_t current_index_;
|
|
|
+ size_t wheel_size_; /* 时间轮最大的轮训次数 */
|
|
|
+ int interval_ms_; /* 每个时间点的间隔秒数 */
|
|
|
+ std::vector<std::list<Task>> wheel_; /* 任务队列,同一个时间点可以有多个链表 */
|
|
|
+ size_t current_index_; /* 现在的时间点 */
|
|
|
bool running_ = false;
|
|
|
std::thread thread_;
|
|
|
std::mutex mutex_;
|