// PHZ // 2018-5-15 #ifndef _XOP_TIMER_H #define _XOP_TIMER_H #include #include #include #include #include #include #include #include #include namespace xop { typedef std::function TimerEvent; typedef uint32_t TimerId; class Timer { public: Timer(const TimerEvent& event, uint32_t msec) : event_callback_(event) , interval_(msec) { if (interval_ == 0) { interval_ = 1; } } static void Sleep(uint32_t msec) { std::this_thread::sleep_for(std::chrono::milliseconds(msec)); } void SetEventCallback(const TimerEvent& event) { event_callback_ = event; } void Start(int64_t microseconds, bool repeat = false) { is_repeat_ = repeat; auto time_begin = std::chrono::high_resolution_clock::now(); int64_t elapsed = 0; do { std::this_thread::sleep_for(std::chrono::microseconds(microseconds - elapsed)); time_begin = std::chrono::high_resolution_clock::now(); if (event_callback_) { event_callback_(); } elapsed = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - time_begin).count(); if (elapsed < 0) { elapsed = 0; } } while (is_repeat_); } void Stop() { is_repeat_ = false; } private: friend class TimerQueue; void SetNextTimeout(int64_t time_point) { next_timeout_ = time_point + interval_; } int64_t getNextTimeout() const { return next_timeout_; } bool is_repeat_ = false; TimerEvent event_callback_ = [] { return false; }; uint32_t interval_ = 0; int64_t next_timeout_ = 0; }; class TimerQueue { public: TimerId AddTimer(const TimerEvent& event, uint32_t msec); void RemoveTimer(TimerId timerId); int64_t GetTimeRemaining(); void HandleTimerEvent(); private: int64_t GetTimeNow(); std::mutex mutex_; std::unordered_map> timers_; std::map, std::shared_ptr> events_; uint32_t last_timer_id_ = 0; }; } #endif