c++ 实现一个js语法的定时器

2020-04-26  本文已影响0人  东京的雨不会淋湿首尔

js 的setTimer和setInterval非常好用,于是想到在c++实现一个类似语法简洁的定时器。
github上已有实现timercpp
其使用方式如下:

Timer t = Timer();

t.setInterval([&]() {
    cout << "Hey.. After each 1s..." << endl;
}, 1000); 

t.setTimeout([&]() {
    cout << "Hey.. After 5.2s. But I will stop the timer!" << endl;
    t.stop();
}, 5200);

非常简洁。可惜项目使用了auto关键字不能用在c++11 的版本上,于是考虑做一些更改,想到我们可以使用模板来实现类似的功能。
完整的实现如下:
(使用方法和上面例子一样)

#include <iostream>
#include <thread>
#include <chrono>

class Timer {
    bool clear = false;

public:
    template<typename Function>
    void setTimeout(Function function, int delay);

    template<typename Function>
    void setInterval(Function function, int interval);

    void stop();
};

template<typename Function>
void Timer::setTimeout(Function function, int delay) {
    this->clear = false;
    std::thread t([=]() {
        if(this->clear) return;
        std::this_thread::sleep_for(std::chrono::milliseconds(delay));
        if(this->clear) return;
        function();
    });
    t.detach();
}

template<typename Function>
void Timer::setInterval(Function function, int interval) {
    this->clear = false;
    std::thread t([=]() {
        while(true) {
            if(this->clear) return;
            std::this_thread::sleep_for(std::chrono::milliseconds(interval));
            if(this->clear) return;
            function();
        }
    });
    t.detach();
}

void Timer::stop() {
    this->clear = true;
}

分析:

接下来我们尝试分析一下原理:
在 setTimeout中,第一行设置用于控制计时器处于活动状态还是非活动状态的标志,以将其设置为活动状态( 不清除该定时器 ):

this->clear = false;

接下来实例化一个新的线程对象,参数是lambda函数,[=]()是指用到的外部元素全部按值操作。

std::thread t([=]() {

该(lambda)函数首先检查timer是否仍处于活动状态(否则它将立即返回),因为它可能已被另一个函数停止。如果处于活动状态,它将等待,sleep_for 会阻塞线程指定的时间:

if(this->clear) return;
std::this_thread::sleep_for(std::chrono::milliseconds(delay));

然后,我们再次检查计时器是否仍处于活动状态,如果是,则调用传递给setTimeout的函数:

if(this->clear) return;
function();

但是这个线程对象的寿命很短:它将在setTimeout函数结束时被销毁。而且我们希望真实线程的寿命超过线程对象的寿命。当thread::detach()函数被调用后,执行的线程从线程对象中被分离,已不再被一个线程对象所表达--这是两个独立的事情。C++线程对象可以被销毁,同时OS执行的线程可以继续。如果程序想要知道执行的线程何时结束,就需要一些其它的机制。

上一篇 下一篇

猜你喜欢

热点阅读