我们公司最近被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;
};

#endif

TimerEventManager *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;
}
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐