172 lines
5.3 KiB
C++
172 lines
5.3 KiB
C++
#ifndef CC_TIMER_H
|
|
#define CC_TIMER_H
|
|
#pragma once
|
|
|
|
#include <CCThread.h>
|
|
#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<milliseconds>(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<microseconds>(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<void()>& callback,unsigned long count,TimeType interval = TimeType::Millisecond);
|
|
// 停止定时器
|
|
void Stop();
|
|
private:
|
|
IntSleep m_sleep;
|
|
std::atomic<bool> 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<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
|