c++ 實現一個js語法的定時器

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執行的線程可以繼續。如果程序想要知道執行的線程何時結束,就需要一些其它的機制。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章