MyTimer
大约 2 分钟cpp
概述
貌似 cpp 里没有系统默认的定时器?网上找了很多文章都是自己实现定时器逻辑的,这里也贴出自己制作使用的定时器
源码
MyTimer.h
#pragma once
#include <functional>
#include <condition_variable>
#include <mutex>
#include <atomic>
using namespace std;
class MyTimer {
public:
MyTimer();
void start(int interval, std::function<void()> task);
void stop();
private:
condition_variable cv;
mutex mut;//与cv配合
atomic<bool> expired; //timer stop status
atomic<bool> tryToExpire;//timer is in stop process.
};
MyTimer.cpp
#pragma once
#include <iostream>
#include <mutex>
#include <thread>
#include <functional>
#include <condition_variable>
#include <atomic>
#include "MyTimer.h"
#pragma region 成员变量
condition_variable cv;
mutex mut;//与cv配合
atomic<bool> expired; //timer stop status
atomic<bool> tryToExpire;//timer is in stop process.
#pragma endregion
#pragma region 成员函数
MyTimer::MyTimer() {
expired = true;
tryToExpire = false;
}
/*
* 子线程执行定时器,每间隔 interval 毫秒执行一次 task
* interval:定时器间隔时间,单位毫秒
* task:定时器执行的任务,调用者传入自己的执行函数名称,要求返回值 void
*/
void MyTimer::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 MyTimer::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;
}
#pragma endregion
使用案例
#include "MyTimer.h"
MyTimer obj;
obj.start(150, mouseClick);// 执行定时器
obj.stop();// 关闭定时器
仓库
该封装工具第一次用于制作热键工具中: gitee仓库
