1 基于C++11特性的微小定时器 - TinyTimer

Github地址:https://github.com/HW140701/TinyTimer

只包含一个头文件的基于C++11特性的微小定时器实现类 -TinyTimer,支持
- 支持同步/异步执行定时器任务;
- 支持中途中断定时器任务,可参考Windows Api的SetTimer和KillTimer;
- 支持多种任务函数类型

代码:
- TinyTimer.hpp

#ifndef TINY_TIMER_H
#define TINY_TIMER_H
#include <functional>
#include <chrono>
#include <thread>
#include <atomic>
#include <memory>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <string>
class TinyTimer
{
public:
typedef std::shared_ptr<TinyTimer> ptr;
virtual~TinyTimer() 
{
KillTimer();
}
TinyTimer() :m_bExpired(true), m_bTryExpired(false), m_bLoopExecute(false)
{
}
TinyTimer(const TinyTimer& t) {
m_bExpired = t.m_bExpired.load();
m_bTryExpired = t.m_bTryExpired.load();
}
public:
//!
//! @brief  设置定时器
//!
//! @param  interval - 定时器执行间隔
//! @param  task - 任务函数
//! @param  bLoop - 是否循环
//! @param  async - 是否异步执行
//!
//! @return 执行结果
//!
bool SetTimer(int interval, std::function<void()> task, bool bLoop = false, bool async = true)
{
if (!m_bExpired || m_bTryExpired)
return false;
m_bExpired = false;
m_bLoopExecute = bLoop;
m_LoopCount = 0;
// 如果是异步执行
if (async)
{
if (m_Thread != nullptr)
m_Thread.reset();
m_Thread = std::make_shared<std::thread>(
([this, interval, task]() {
while (!m_bTryExpired)
{
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
task();
m_LoopCount++;
if (!m_bLoopExecute)
{
break;
}
}
{
std::lock_guard<std::mutex> locker(m_ThreadMutex);
m_bExpired = true;
m_bTryExpired = false;
m_ExpiredConditionVar.notify_one();
}
})
);
m_Thread->detach();
}
// 如果是同步执行
else
{
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
if (!m_bTryExpired) {
task();
}
m_bExpired = true;
m_bTryExpired = false;
}
return true;
}
//!
//! @brief  杀死定时器
//!
void KillTimer()
{
if (m_bExpired || m_bTryExpired || m_Thread == nullptr)
{
return;
}
m_bTryExpired = true;
{
std::unique_lock<std::mutex> locker(m_ThreadMutex);
m_ExpiredConditionVar.wait(locker, [this] {return m_bExpired == true; });
if (m_bExpired == true) {
m_bTryExpired = false;
}
}
}
//!
//! @brief  异步延迟执行一次定时器
//!
//! @param  interval - 定时器执行间隔
//! @param  fun - 任务函数
//!
//! @return 执行结果
//!
template<typename callable, typename... arguments>
bool AsyncOnceExecute(int interval, callable&& fun, arguments&&... args) {
std::function<typename std::result_of<callable(arguments...)>::type()> task(std::bind(std::forward<callable>(fun), std::forward<arguments>(args)...));
return SetTimer(interval, task, false);
}
//!
//! @brief  异步定时循环执行定时器
//!
//! @param  interval - 定时器执行间隔
//! @param  fun - 任务函数
//!
//! @return 执行结果
//!
template<typename callable, typename... arguments>
bool AsyncLoopExecute(int interval, callable&& fun, arguments&&... args) {
std::function<typename std::result_of<callable(arguments...)>::type()> task(std::bind(std::forward<callable>(fun), std::forward<arguments>(args)...));
return SetTimer(interval, task, true);
}
//!
//! @brief  同步执行一次定时器
//!
//! @param  interval - 定时器执行间隔
//! @param  fun - 任务函数
//!
//! @return 执行结果
//!
template<typename callable, typename... arguments>
bool SyncOnceExecute(int interval, callable&& fun, arguments&&... args) {
std::function<typename std::result_of<callable(arguments...)>::type()> task(std::bind(std::forward<callable>(fun), std::forward<arguments>(args)...)); //绑定任务函数或lambda成function
return SetTimer(interval, task, false, false);
}
private:
std::atomic_bool m_bExpired;
std::atomic_bool m_bTryExpired;
std::atomic_bool m_bLoopExecute;
std::mutex m_ThreadMutex;
std::condition_variable m_ExpiredConditionVar;
std::shared_ptr<std::thread> m_Thread;
unsigned int m_LoopCount = 0;
};
#endif // !TINY_TIMER_H

2 使用示例

2.1 静态/全局作为任务函数

#include <iostream>
#include "conio.h"
#include "TinyTimer.hpp"
using namespace std;
void Print()
{
std::cout << "定时器全局函数Print执行" << std::endl;
}
int main()
{
TinyTimer::ptr tinyTimer = std::make_shared<TinyTimer>();
// 延迟1秒执行1次静态/全局函数
tinyTimer->AsyncOnceExecute(1000, Print);
tinyTimer->KillTimer();
// 循环执行静态/全局函数,按Q键杀死定时器
int a = 0;
while (true)
{
// 在此处填入需要循环的代码
if (a == 0)
{
tinyTimer->AsyncLoopExecute(1, Print);
}
if (_kbhit()) // 如果有按键被按下
{
if (_getch() == 'q') //如果按下了q键则跳出循环
{
tinyTimer->KillTimer();
break;
}
}
}
getchar();
return 0;
}

2.2 Lambda表达式作为任务函数

#include <iostream>
#include "conio.h"
#include "TinyTimer.hpp"
using namespace std;
int main()
{
TinyTimer::ptr tinyTimer = std::make_shared<TinyTimer>();
// 延迟1秒执行lambda函数表达式
tinyTimer->AsyncOnceExecute(1000, []() {
std::cout << "Lambda函数执行" << std::endl;
});
tinyTimer->KillTimer();
getchar();
return 0;
}

2.3 类成员函数做为任务函数

#include <iostream>
#include "conio.h"
#include "TinyTimer.hpp"
using namespace std;
void Print()
{
std::cout << "定时器全局函数Print执行" << std::endl;
}
class Task
{
public:
Task() {
};
~Task() {
};
void TaskRun()
{
std::cout << "Task::TaskRun()函数执行" << std::endl;
};
};
int main()
{
TinyTimer::ptr tinyTimer = std::make_shared<TinyTimer>();
// 延迟1秒执行1次类成员函数
Task taskObj;
std::function<void(void)> taskRunFunc = std::bind(&Task::TaskRun, taskObj);
tinyTimer->AsyncOnceExecute(1000, taskRunFunc);
tinyTimer->KillTimer();
getchar();
return 0;
}

参考