可以直接使用c++11的thread, mutex, conditon_variable來實作, 結合了std::function.
Note:
1)start函數,開辟一個新的線程,并detach,在這個線程中周期性地執行task。
建立一個std::thread線程時,需要傳入一個可調用對象,這裡使用了lambda函數,非常友善。
start函數的入參是,周期時間ms,以及一個std::function<void()>
2) 使用了c++11的原子變量automic<bool>,比較友善。
3)stop函數的作用是給已經正在運作的任務線程發一個通知(通過改變一個bool成員變量),然後使用一個conditon_variable進入等待狀态。
任務線程會在每次執行新一輪的任務時檢查該變量的值,并判斷是否停止, 停止後,會使用condition_variable通知stop函數不用等待了。
#pragma once
#include <iostream>
#include <mutex>
#include <thread>
#include <functional>
#include <condition_variable>
#include <atomic>
using namespace std;
class MyTimer {
public:
MyTimer() {
expired = true;
tryToExpire = false;
}
//interval: ms
void start(int interval, std::function<void()> task)
{
if (expired == false)//has already started, do not start again
return;
// start async timer, launch thread and wait in that thread
expired = false;
//将lambda函數傳遞給線程,做線程函數
std::thread([this, interval, task]() {
//小缺點:在task執行的過程中設定tryToExpire為true的話,需要等到本次task執行完畢後才能被while條件判斷檢測到。
while (!tryToExpire)
{
// sleep every interval and do the task again and again until times up
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
task(); //call this function every interval milliseconds.
}
// timer be stopped, update the condition variable expired and wake main thread
std::lock_guard<std::mutex> locker(mut);
expired = true;
cv.notify_one();
}).detach();
}
void stop()//該接口負責修改tryToExipired的值。
{
// do not stop again
if (expired)
return;
if (tryToExpire)
return;
// wait until timer
tryToExpire = true; // change this bool value to make timer while loop stop. This val is atomic type.
std::unique_lock<std::mutex> locker(mut);
cv.wait(locker, [this] {return expired == true; });//不給lambda函數串this,不能使用成員變量expired!
// reset the timer,
//成功停止後,設定tryToExpire為false. 其實,可以不使用wait動作,将tryToExpire=false的動作放到
//start函數,當while循環被打斷後,立即設定tryToExpire為false。
//但是,這樣單獨放在這裡設定也有好處吧,實作了tryToExipired的值僅僅由該stop函數負責。例如,任務線程成功結束後,這裡可以進行一些額外的善後動作,
if (expired == true)
tryToExpire = false;
}
private:
condition_variable cv;
mutex mut;//與cv配合
atomic<bool> expired; //timer stop status
atomic<bool> tryToExpire;//timer is in stop process.
};
Test:
void printNum() {
static int a = 0;
a++;
cout << "a=" << a << endl;
}
void main() {
MyTimer obj;
obj.start(1000,printNum);
getchar();//定時線程執行了detatch,這裡需要等待才能看到起輸出數字到螢幕上
obj.stop();
getchar();
return;
}
Ref:
https://blog.csdn.net/u012234115/article/details/89857431
https://www.cnblogs.com/grandyang/p/4340948.html