USB_Config_Vendor/CC_SDK/Include/basic/CCTimer.h
2026-02-03 14:36:30 +08:00

161 lines
4.8 KiB
C++

#ifndef CC_TIMER_H
#define CC_TIMER_H
#pragma once
#include <CCThread.h>
#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<milliseconds>(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<bool> m_running{};
std::thread m_thread;
std::mutex m_mutex;
int m_count = 0;
inline static Map<int,std::function<void()>> m_callback;
#ifdef _WIN32
HANDLE timerHandle{};
#else
#endif
public:
Timer();
~Timer();
// 启动定时器
void Start(const std::function<void()>& 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<int*>(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<size_t,ClockCallBack*> 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