70 : wheel_size_(wheel_size),
71 tick_interval_ms_(tick_interval_ms),
84 return add_task_internal(delay_ms, std::move(task),
false);
96 return add_task_internal(interval_ms, std::move(task),
true);
109 std::lock_guard<std::mutex> lock(mutex_);
110 auto it = task_map_.find(
id);
111 if (it != task_map_.end()) {
112 it->second->cancelled =
true;
132 std::list<std::shared_ptr<TimerNode>> tasks_to_run;
133 std::list<std::shared_ptr<TimerNode>> tasks_to_reschedule;
136 std::lock_guard<std::mutex> lock(mutex_);
138 current_tick_ = (current_tick_ + 1) % wheel_size_;
139 auto& slot = wheel_[current_tick_];
141 for (
auto it = slot.begin(); it != slot.end(); ) {
145 if (node->cancelled) {
146 task_map_.erase(node->id);
151 if (node->remaining_laps > 0) {
152 node->remaining_laps--;
156 tasks_to_run.push_back(node);
159 if (node->is_periodic) {
160 tasks_to_reschedule.push_back(node);
163 task_map_.erase(node->id);
171 for (
auto& node : tasks_to_reschedule) {
172 if (!node->cancelled) {
173 int target_slot = (current_tick_ + node->interval_ticks) % wheel_size_;
174 node->remaining_laps = (node->interval_ticks - 1) / wheel_size_;
175 wheel_[target_slot].push_back(node);
181 for (
auto& node : tasks_to_run) {
182 if (!node->cancelled && node->task) {
205 : id(id_), remaining_laps(laps), interval_ticks(interval),
206 is_periodic(periodic), cancelled(false), task(std::move(t)) {}
217 if (delay_ms <= 0 || !task) {
225 int ticks_to_wait = (delay_ms + tick_interval_ms_ - 1) / tick_interval_ms_;
227 std::lock_guard<std::mutex> lock(mutex_);
230 int remaining_laps = (ticks_to_wait - 1) / wheel_size_;
231 int target_slot = (current_tick_ + ticks_to_wait) % wheel_size_;
233 auto node = std::make_shared<TimerNode>(
234 id, remaining_laps, ticks_to_wait, periodic, std::move(task)
237 wheel_[target_slot].push_back(node);
238 task_map_[id] = node;
243 const int wheel_size_;
244 const int tick_interval_ms_;
245 int current_tick_ = 0;
248 std::vector<std::list<std::shared_ptr<TimerNode>>> wheel_;
250 std::unordered_map<TimerTaskId, std::shared_ptr<TimerNode>> task_map_;
252 std::atomic<TimerTaskId> next_task_id_;