c++自定义定时器
我们公司最近被qt公司盯上说侵权,现在在去qt化,本博文的定时器可以代替QTimer。
#ifndef TIMEERCPP_H
#define TIMEERCPP_H#include <thread>
#include <atomic>class Timer
{
public:void setInterval(int interval);~Timer();void stop();void start();private:void run();std::atomic<bool> active{false};int interval{1000};std::thread workerThread;
};#endif#include "timercpp.h"
#include <iostream>
#include <thread>void Timer::setInterval(int interval)
{this->interval = interval;
}Timer::~Timer()
{if(active.load()){stop();}
}void Timer::stop()
{active = false;if(workerThread.joinable()){workerThread.join();}
}void Timer::start()
{if(active.load()){stop();}active = true;workerThread = std::thread(&Timer::run, this);
}void Timer::run()
{std::cout<<"run"<<std::endl;while(active.load()){std::this_thread::sleep_for(std::chrono::milliseconds(interval));if(!active.load())return;std::cout<<"xxx"<<std::endl;}
}
这个代码可用,不卡GUI,缺点是每创建一个对象就创建一个子线程。
下面这个代码则进行了优化,使用一个子线程统一处理:
#ifndef TIMEERCPP_H
#define TIMEERCPP_H#include <thread>
#include <atomic>
#include <list>
#include <mutex>
#include <chrono>class Timer
{
public:Timer();~Timer();void updateTime(long long currentTime_millisec);void setInterval(int newInterval);private:long long millisec_since_epoch_currentTime;int interval{1000};int GC{0};
};class TimerEventManager
{
public:static TimerEventManager* getInstance();~TimerEventManager();void addTimer(Timer * timer);void removeTimer(Timer * timer);void start();void stop();private:void run();std::list<Timer*> list;std::atomic<bool> active{false};std::thread workerThread;std::mutex mutex;
};#endifTimerEventManager *TimerEventManager::getInstance()
{static TimerEventManager manager;return &manager;
}TimerEventManager::~TimerEventManager()
{active = false;if(workerThread.joinable()){workerThread.join();}
}void TimerEventManager::addTimer(Timer *timer)
{std::lock_guard<std::mutex> lock(mutex);list.push_back(timer);
}void TimerEventManager::removeTimer(Timer *timer)
{std::lock_guard<std::mutex> lock(mutex);list.remove(timer);
}void TimerEventManager::start()
{active.store(true);workerThread = std::thread(&TimerEventManager::run,this);
}void TimerEventManager::stop()
{active.store(false);if (workerThread.joinable()){workerThread.join();}
}void TimerEventManager::run()
{while(active.load()){std::this_thread::sleep_for(std::chrono::milliseconds(50));if (!active.load())return;auto currentTime_millisec = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();std::lock_guard<std::mutex> lock(mutex);for (auto& timer : list){timer->updateTime(currentTime_millisec);}}
}Timer::Timer()
{//获取时间点相对于 epoch(通常是 1970 年 1 月 1 日 00:00:00 UTC)的持续时间的函数。millisec_since_epoch_currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();TimerEventManager::getInstance()->addTimer(this);
}Timer::~Timer()
{TimerEventManager::getInstance()->removeTimer(this);
}void Timer::updateTime(long long currentTime_millisec)
{int t = (currentTime_millisec - millisec_since_epoch_currentTime) / interval;if(t > GC){GC = t;std::cout<<"超时 interval = "<<interval<<std::endl;}
}void Timer::setInterval(int newInterval)
{interval = newInterval;
}