#ifndef CC_TIMER_H #define CC_TIMER_H #pragma once #include #include "CC.h" #include "CCPrecisionClock" namespace CTL { class ClockTimer{ size_t last_time{}; size_t last_duration = 10; size_t deviation{}; size_t sleep_time_ms = 100; inline static size_t initAccuracy = {}; bool ImprovePrecision = true; public: static void initializationAccuracy(const size_t ms){ initAccuracy = ms; #ifdef _WIN32 timeBeginPeriod(ms); #endif } static void finalizationAccuracy(){ #ifdef _WIN32 timeEndPeriod(initAccuracy); #endif } size_t sleepMS(const size_t ms){ last_time = ms; using namespace std::chrono; const auto start = high_resolution_clock::now(); const auto target = start + milliseconds(ms) - milliseconds(deviation); if (ms > last_duration) { const auto a = last_duration / 3; const auto b = ms - a - deviation; if (b > 0) { CTL::Thread::SleepMS(b); } } while (high_resolution_clock::now() < target) { if (!ImprovePrecision) { CTL::Thread::Sleep(1); } } const auto end = high_resolution_clock::now(); const auto actual_duration = duration_cast(end - start).count(); deviation = actual_duration - ms; return actual_duration; } void resetDeviation(){ deviation = 0; } void improvePrecision(const bool Flag){ ImprovePrecision = Flag; } }; enum TimeType { Millisecond = 1, Second = 2, Minute = 3, Hour = 4, }; class Timer { IntSleep m_sleep; std::atomic m_running{}; std::thread m_thread; std::mutex m_mutex; int m_count = 0; inline static Map> m_callback; #ifdef _WIN32 HANDLE timerHandle{}; #else #endif public: Timer(); ~Timer(); // 启动定时器 void Start(const std::function& callback,unsigned long count,TimeType interval = TimeType::Millisecond); // 停止定时器 void Stop(); private: int AssignmentID(); #ifdef _WIN32 static VOID CALLBACK TimerCallback(PVOID lpParam, BOOLEAN TimerOrWaitFired) { int count = *static_cast(lpParam); const auto func = m_callback.get(count); if (func) { try { func->operator()(); } catch (CCException& e) { System::Println("Timer CallBack Error: {}",e.what()); } } } #else #endif }; 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