diff --git a/include/sled/task_queue/task_queue_base.h b/include/sled/task_queue/task_queue_base.h index 7fced21..4c17666 100644 --- a/include/sled/task_queue/task_queue_base.h +++ b/include/sled/task_queue/task_queue_base.h @@ -30,21 +30,21 @@ public: virtual void Delete() = 0; - void PostTask(std::function &&task, - const Location &location = Location::Current()) + inline void PostTask(std::function &&task, + const Location &location = Location::Current()) { PostTaskImpl(std::move(task), PostTaskTraits{}, location); } - void PostDelayedTask(std::function &&task, - TimeDelta delay, - const Location &location = Location::Current()) + inline void PostDelayedTask(std::function &&task, + TimeDelta delay, + const Location &location = Location::Current()) { PostDelayedTaskImpl(std::move(task), delay, PostDelayedTaskTraits{}, location); } - void + inline void PostDelayedHighPrecisionTask(std::function &&task, TimeDelta delay, const Location &location = Location::Current()) @@ -53,7 +53,7 @@ public: PostDelayedTaskImpl(std::move(task), delay, traits, location); } - void + inline void PostDelayedTaskWithPrecision(DelayPrecision precision, std::function &&task, TimeDelta delay, diff --git a/include/sled/timer/timer.h b/include/sled/timer/timer.h index 3c7183d..85e6a24 100644 --- a/include/sled/timer/timer.h +++ b/include/sled/timer/timer.h @@ -26,7 +26,7 @@ public: const DurationMs &duration() const { return duration_; } - int expireation_count() const { return expiration_count_; } + int expiration_count() const { return expiration_count_; } bool is_running() const { return is_running_; } @@ -38,6 +38,7 @@ private: OnExpired on_expired, UnregisterHandler unregister_handler, std::unique_ptr timeout); + void Trigger(TimerGeneration generation); const TimerID id_; const std::string name_; diff --git a/src/synchronization/event.cc b/src/synchronization/event.cc index dc1aacf..5b160cc 100644 --- a/src/synchronization/event.cc +++ b/src/synchronization/event.cc @@ -1,7 +1,7 @@ #include "sled/synchronization/event.h" namespace sled { -// constexpr TimeDelta Event::kForever; +constexpr TimeDelta Event::kForever; Event::Event() : Event(false, false) {} diff --git a/src/timer/task_queue_timeout.cc b/src/timer/task_queue_timeout.cc index 0e8b978..e0a3fd2 100644 --- a/src/timer/task_queue_timeout.cc +++ b/src/timer/task_queue_timeout.cc @@ -16,6 +16,7 @@ void TaskQueueTimeoutFactory::TaskQueueTimeout::Start(DurationMs duration_ms, TimeoutID timeout_id) { + ASSERT(timeout_expiration_ == std::numeric_limits::max(), ""); timeout_expiration_ = parent_.get_time_() + duration_ms; timeout_id_ = timeout_id; @@ -30,19 +31,25 @@ TaskQueueTimeoutFactory::TaskQueueTimeout::Start(DurationMs duration_ms, parent_.task_queue_.PostDelayedTaskWithPrecision( precision_, [timeout_id, this]() { + LOGV("timer", "Timeout expired: {}", timeout_id); + ASSERT(posted_task_expiration_ + != std::numeric_limits::max(), + ""); posted_task_expiration_ = std::numeric_limits::max(); + if (timeout_expiration_ == std::numeric_limits::max()) { // cancelled timer // do nothing } else { - DurationMs remaining = - timeout_expiration_ - parent_.get_time_(); - timeout_expiration_ = std::numeric_limits::max(); - if (remaining > 0) { - Start(remaining, timeout_id); - } else { - LOGD("", "Timeout Triggered: {}", timeout_id); + const TimeMs now = parent_.get_time_(); + if (timeout_expiration_ <= now) { + timeout_expiration_ = std::numeric_limits::max(); + LOGD("timer", "Timeout Triggered: {}", timeout_id); parent_.on_expired_(timeout_id_); + } else { + const DurationMs remaining = timeout_expiration_ - now; + timeout_expiration_ = std::numeric_limits::max(); + Start(remaining, timeout_id); } } }, diff --git a/src/timer/timer.cc b/src/timer/timer.cc index 6865efc..2908c6a 100644 --- a/src/timer/timer.cc +++ b/src/timer/timer.cc @@ -42,6 +42,40 @@ Timer::Start() } } +void +Timer::Stop() +{ + if (is_running()) { + timeout_->Stop(); + expiration_count_ = 0; + is_running_ = false; + } +} + +void +Timer::Trigger(TimerGeneration generation) +{ + if (!is_running_ || generation != generation_) { return; } + ++expiration_count_; + is_running_ = false; + // if max_restarts > exppiration_count_ then restart + { + is_running_ = true; + generation_ = TimerGeneration(generation_ + 1); + timeout_->Start(duration_, MakeTimeoutId(id_, generation_)); + } + + sled::optional new_duration = on_expired_(); + if (new_duration.has_value() && new_duration != duration_) { + duration_ = new_duration.value(); + if (is_running_) { + timeout_->Stop(); + generation_ = TimerGeneration(generation_ + 1); + timeout_->Start(duration_, MakeTimeoutId(id_, generation_)); + } + } +} + std::unique_ptr TimerManager::CreateTimer(const std::string &name, Timer::OnExpired on_expired) { @@ -57,4 +91,13 @@ TimerManager::CreateTimer(const std::string &name, Timer::OnExpired on_expired) timers_[id] = timer.get(); return timer; } + +void +TimerManager::HandleTimeout(TimeoutID id) +{ + TimerID timer_id = id >> 32; + TimerGeneration generation = id & 0xffffffff; + auto it = timers_.find(timer_id); + if (it != timers_.end()) { it->second->Trigger(generation); } +} }// namespace sled