| 72 | } |
| 73 | |
| 74 | void Timers::addTask(std::shared_ptr<TimerTask> task) { |
| 75 | if (task->queued_) { |
| 76 | return; |
| 77 | } |
| 78 | auto now = now_ms(); |
| 79 | task->nestingLevel_ = nesting + 1; |
| 80 | task->queued_ = true; |
| 81 | // theoretically this should be >5 on the spec, but we're following chromium behavior here again |
| 82 | if (task->nestingLevel_ >= 5 && task->frequency_ < 4) { |
| 83 | task->frequency_ = 4; |
| 84 | task->startTime_ = now; |
| 85 | } |
| 86 | timerMap_.emplace(task->id_, task); |
| 87 | auto newTime = task->NextTime(now); |
| 88 | task->dueTime_ = newTime; |
| 89 | bool needsScheduling = true; |
| 90 | if (!isBufferFull.load() && task->dueTime_ <= now) { |
| 91 | auto result = write(fd_[1], &task->id_, sizeof(int)); |
| 92 | if (result != -1 || errno != EAGAIN) { |
| 93 | needsScheduling = false; |
| 94 | } else { |
| 95 | isBufferFull = true; |
| 96 | } |
| 97 | } |
| 98 | if (needsScheduling) { |
| 99 | { |
| 100 | std::lock_guard<std::mutex> lock(mutex); |
| 101 | auto it = sortedTimers_.begin(); |
| 102 | auto dueTime = task->dueTime_; |
| 103 | it = std::upper_bound(sortedTimers_.begin(), sortedTimers_.end(), dueTime, |
| 104 | [](const double &value, |
| 105 | const std::shared_ptr<TimerReference> &ref) { |
| 106 | return ref->dueTime > value; |
| 107 | }); |
| 108 | auto ref = std::make_shared<TimerReference>(); |
| 109 | ref->dueTime = task->dueTime_; |
| 110 | ref->id = task->id_; |
| 111 | sortedTimers_.insert(it, ref); |
| 112 | } |
| 113 | taskReady.notify_one(); |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | void Timers::removeTask(const std::shared_ptr<TimerTask> &task) { |
| 118 | removeTask(task->id_); |