| #ifndef PLATFORMS_VBMC_TIMER_TIMER_H_ |
| #define PLATFORMS_VBMC_TIMER_TIMER_H_ |
| |
| #include <cstdint> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "absl/base/thread_annotations.h" |
| #include "absl/functional/any_invocable.h" |
| #include "absl/status/status.h" |
| #include "absl/strings/string_view.h" |
| #include "absl/synchronization/mutex.h" |
| #include "absl/time/time.h" |
| #include "utils/thread.h" |
| #include "utils/clock.h" |
| |
| namespace milotic { |
| |
| enum TimerState : std::uint8_t { |
| kIdle = 0, |
| kTicking, |
| kRestart, |
| kCallbackRunning, |
| kCallbackDone, |
| kEnd, |
| }; |
| |
| std::string TimerStateToString(TimerState state); |
| |
| /* |
| * Timer |
| * Used to create a timer in a new thread which calls TimerCallback on timeout. |
| * |
| * Timer duration is set while calling the Start method and which can be reset |
| * using Restart() with the new duration. |
| * |
| * Start() should only be called once, multiple invocations will not create |
| * multiple timers. |
| * Restart() can be called multiple times before timer callback. |
| * Reset() ends the current timer and allows Start to be called again. |
| * |
| * TimerCallback function must be set before Start() is called. |
| */ |
| class Timer { |
| public: |
| using TimerCallback = absl::AnyInvocable<void() const>; |
| using Ticker = absl::AnyInvocable<void() const>; |
| |
| explicit Timer(TimerCallback callback, absl::string_view timer_name = "Timer", |
| util::Clock* clock = util::Clock::RealClock()) |
| : timer_name_(timer_name), |
| callback_(std::move(callback)), |
| clock_(clock) {} |
| |
| ~Timer(); |
| |
| // Not Copyable |
| Timer(const Timer&) = delete; |
| Timer& operator=(const Timer&) = delete; |
| |
| // Not Movable |
| Timer(Timer&&) = delete; |
| Timer& operator=(Timer&&) = delete; |
| |
| absl::Status Start(absl::Duration duration, Ticker ticker = nullptr); |
| absl::Status Restart(absl::Duration duration); |
| void Reset(); |
| void End(); |
| bool IsCallbackDone() { |
| absl::MutexLock guard(timer_mutex_); |
| return callback_done_; |
| } |
| |
| bool IsRunning() { |
| absl::MutexLock guard(timer_mutex_); |
| return state_ != kIdle && state_ != kEnd; |
| } |
| |
| private: |
| std::string timer_name_; |
| TimerCallback callback_; |
| std::unique_ptr<MiloticThread> tick_thread_; |
| absl::Mutex timer_mutex_; |
| util::Clock* const clock_; |
| absl::Duration duration_ ABSL_GUARDED_BY(timer_mutex_); |
| TimerState state_ ABSL_GUARDED_BY(timer_mutex_) = kIdle; |
| bool callback_done_ ABSL_GUARDED_BY(timer_mutex_) = false; |
| |
| void Tick(); |
| bool CheckRestartOrEnd(); |
| bool CheckTickingOrEnd(); |
| void CallbackWrapper(); |
| }; |
| |
| } // namespace milotic |
| |
| #endif // PLATFORMS_VBMC_TIMER_TIMER_H_ |