#ifndef CC_TIMER_H #define CC_TIMER_H #pragma once #include #include "CCPrecisionClock" #include "CC.h" namespace CTL { class ClockTimer{ long last_time{}; long current_time{}; long base_duration = 10; long deviation{}; long sleep_time_ms = 100; inline static long initAccuracy = {}; bool ImprovePrecision = true; public: static void initializationAccuracy(const long ms){ initAccuracy = ms; #ifdef _WIN32 timeBeginPeriod(ms); #endif } static void finalizationAccuracy(){ #ifdef _WIN32 timeEndPeriod(initAccuracy); #endif } long sleepMS(const long ms){ using namespace std::chrono; const auto start = high_resolution_clock::now(); const long p_ms = ms - deviation; const auto target = start + milliseconds(p_ms); if (p_ms > base_duration) { const long a = base_duration / 3; const auto b = p_ms - a; if (b > 0) { Thread::SleepMS(b); } else { deviation = b; return b; } } while (high_resolution_clock::now() < target) { if (!ImprovePrecision) { Thread::Sleep(1); } } const auto end = high_resolution_clock::now(); const long long actual_duration = duration_cast(end - start).count(); deviation = actual_duration - p_ms; return actual_duration; } size_t sleepUS(const long us){ using namespace std::chrono; const auto start = high_resolution_clock::now(); current_time = us - deviation; const auto target = start + microseconds(us) - microseconds(deviation); if (current_time > base_duration) { const auto a = base_duration / 3; const auto b = current_time - a; if (b > 0) { Thread::Sleep(b); } } while (high_resolution_clock::now() < target) { if (!ImprovePrecision) { Thread::Sleep(1); } } const auto end = high_resolution_clock::now(); last_time = duration_cast(end - start).count(); if (current_time == last_time) { deviation = 0; } else { deviation = last_time - current_time; } return last_time; } void resetDeviation(){ deviation = 0; } void improvePrecision(const bool Flag){ ImprovePrecision = Flag; } }; enum TimeType { Microsecond = 0, Millisecond = 1, Second = 2, Minute = 3, Hour = 4, }; class Timer { public: Timer(); ~Timer(); // 启动定时器 void Start(const std::function& callback,unsigned long count,TimeType interval = TimeType::Millisecond); // 停止定时器 void Stop(); private: IntSleep m_sleep; std::atomic m_running{}; std::thread m_thread; std::mutex m_mutex; }; class ClockCallBack{ std::condition_variable cv; std::mutex mtx; size_t count = {}; size_t sleep_time_ms = {}; size_t timer_id = {}; inline static CTL::Map m_callback; inline static CCMutex mutex; inline static std::atomic_bool is_running = {}; inline static Thread* m_thread = nullptr; static size_t getID(){ for (int i = 0; i < 1000000; ++i) { if (!m_callback.IsContains(i)) { return i; } } return -1; } public: static void Init(){ is_running.store(true); m_thread = new Thread(); m_thread->SetThread([&]() { while (is_running.load()) { millisecond_delay(1); CCUniqueLock lock(mutex); for (const auto &[id,callback] : m_callback) { if (callback && callback->sleep_time_ms > 0) { callback->count++; if (callback->count >= callback->sleep_time_ms) { callback->cv.notify_all(); callback->count = 0; } } } } }); m_thread->Start(); } static void Release(){ is_running.store(false); delete m_thread; } void start(){ CCUniqueLock lock(mutex); this->timer_id = getID(); m_callback.put(timer_id,this); } void sleep(const size_t us){ CCUniqueLock lock(mtx); this->sleep_time_ms = us; cv.wait_for(lock, std::chrono::milliseconds(sleep_time_ms)); } void stop() const{ CCUniqueLock lock(mutex); m_callback.Remove(timer_id); } }; } #endif