| /* |
| * Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license |
| * that can be found in the LICENSE file. |
| */ |
| |
| #pragma once |
| |
| #include <condition_variable> |
| #include <mutex> |
| #include <string_view> |
| |
| #include "Clock.hpp" |
| #include "KAssert.h" |
| #include "concurrent/UtilityThread.hpp" |
| #include "Utils.hpp" |
| |
| namespace kotlin { |
| |
| template <typename Clock = steady_clock> |
| class RepeatedTimer : private Pinned { |
| public: |
| template <typename Rep, typename Period, typename F> |
| RepeatedTimer(std::string_view name, std::chrono::duration<Rep, Period> interval, F&& f) noexcept : |
| interval_(interval), |
| next_(Clock::now() + interval_), |
| thread_(name, &RepeatedTimer::Run<F>, this, std::forward<F>(f)) {} |
| |
| template <typename Rep, typename Period, typename F> |
| RepeatedTimer(std::chrono::duration<Rep, Period> interval, F&& f) noexcept : |
| RepeatedTimer("Timer thread", interval, std::forward<F>(f)) {} |
| |
| ~RepeatedTimer() { |
| { |
| std::unique_lock lock(mutex_); |
| run_ = false; |
| scheduledInterrupt_ = true; |
| } |
| wait_.notify_all(); |
| // Make sure we wait for the thread to finish before starting to destroy the fields. |
| thread_.join(); |
| } |
| |
| template <typename Rep, typename Period> |
| void restart(std::chrono::duration<Rep, Period> interval) noexcept { |
| { |
| std::unique_lock lock(mutex_); |
| interval_ = interval; |
| next_ = Clock::now() + interval_; |
| scheduledInterrupt_ = true; |
| } |
| wait_.notify_all(); |
| } |
| |
| private: |
| template <typename F> |
| void Run(F&& f) noexcept { |
| std::unique_lock lock(mutex_); |
| while (run_) { |
| scheduledInterrupt_ = false; |
| if (Clock::wait_until(wait_, lock, next_, [this] { return scheduledInterrupt_; })) { |
| continue; |
| } |
| // The function must be executed in the unlocked environment. |
| lock.unlock(); |
| std::invoke(std::forward<F>(f)); |
| lock.lock(); |
| next_ = Clock::now() + interval_; |
| } |
| } |
| |
| std::mutex mutex_; |
| std::condition_variable wait_; |
| bool run_ = true; |
| typename Clock::duration interval_; |
| std::chrono::time_point<Clock> next_; |
| bool scheduledInterrupt_ = false; |
| UtilityThread thread_; |
| }; |
| |
| } // namespace kotlin |