timer定时器,多线程,回调为阻塞模式。支持参数绑定,非常好使。
用法:
//////////////////////////////////////////////////////////////////////////
//以下是测试代码
namespace timertester
{
class timertestclass
{
public:
timertestclass(){};
~timertestclass(){};
void testfn()
{
printf("timer callback is class func.\n");
FTimerEvent mTimer(3000, &timertestclass::threadfn, this);
for (int i = 0; i < 5; i++)
{
printf("press any key to ...\n");
getchar();
mTimer.SetTimerEvent();
}
printf("stop timer \n");
mTimer.StopTimer();
}
void threadf(int i)
{
printf("test f i:%d\n", i);
}
void threadfn()
{
printf("test fn d\n");
}
void threadfn2()
{
printf("test fn2222 \n");
}
};
static void testfn1(timertestclass *cls)
{
cls->threadfn();
}
static void testpf()
{
printf("test printf \n");
printf("callback ret. \n");
}
static void prt(int& i)
{
printf("print %d\n", i);
}
static void timertest()
{
int t = 0;
FTimerEvent timerstdref(1000, prt, std::ref(t));
for (int i = 0; i < 10; i++)
{
t = i;
Sleep(1000);
}
timerstdref.StopTimer();
{
printf("timer 0 manual to set\n");
//如果定时为0,则每次为手动触发
FTimerEvent timerman(0, [](){
printf("timerman in.\n");
Sleep(5000);
printf("timerman out.\n");
});
timerman.SetTimerEvent();
timerman.SetTimerEvent();
timerman.StopTimer();
}
printf("stop timer in callback\n");
FTimerEvent timer4;
timer4.InitTimer(1000, [](FTimerEvent *pTimer){ printf("exit timer\n"); pTimer->StopTimer(); }, &timer4);
Sleep(3000);
timer4.StopTimer();
printf("set timer in callback\n");
FTimerEvent timer5;
timer5.InitTimer(2000, [](FTimerEvent *pTimer){
static bool set = false;
printf("timer in\n");
if (!set)
{
printf("set timer\n");
pTimer->SetTimerEvent();
set = true;
}
printf("timer out\n");
}, &timer5);
Sleep(10000);
timer5.StopTimer();
timertestclass test1;
test1.testfn();
int x = 0;
FTimerEvent timerref(1000, [&x]()
{
printf("x: %d \n", x);
});
for (int i = 0; i < 10; i++)
{
x = i;
Sleep(1000);
}
timerref.StopTimer();
FTimerEvent timerx(1000, [&test1]()
{
test1.threadfn2();
});
Sleep(10000);
timerx.StopTimer();
FTimerEvent timer0(1000, testpf);
Sleep(10000);
timer0.StopTimer();
FTimerEvent timer1(1000, testfn1, &test1);
Sleep(10000);
timer1.StopTimer();
FTimerEvent timer2(1000, [](){ printf("lambada no param \n"); });
Sleep(10000);
timer2.StopTimer();
int param = 0;
FTimerEvent timer3(1000, [](int *p){ printf("lambada with param: %d \n", *p); }, ¶m);
Sleep(10000);
timer3.StopTimer();
}
}
Timer.h
#pragma once
#include <thread>
#include <functional>
#include <chrono>
#include <future>
#include <mutex>
#include <atomic>
#include <condition_variable>
class FTimerEvent
{
private:
std::mutex m_mtx;
std::condition_variable m_Condition;
std::future<int> m_loopTask;
std::thread::id m_loopThreadID;
//回调函数
std::function<void()> m_funCallback;
//退出标记
bool m_bExit;
std::atomic<int> m_nManual;
void _InitTimer(uint32_t nTimeout)
{
m_nManual = 0;
m_loopTask = std::async(std::launch::async, [this, nTimeout]()->int{
printf("timer thread start...\n");
//保存线程ID
m_loopThreadID = std::this_thread::get_id();
while (!m_bExit || m_nManual)
{
//wait for timeout
std::unique_lock<std::mutex> lock(m_mtx);
//bool waitret = false;
if (nTimeout)
m_Condition.wait_for(lock, std::chrono::milliseconds(nTimeout), [this](){return (m_nManual != 0); });
else
m_Condition.wait(lock, [this](){return (m_nManual != 0); });
if (m_bExit && m_nManual == 0)
return 0;
if (m_nManual)
m_nManual--;
//callback
//printf("timer call back ... \n");
m_funCallback();
}
printf("timer thread exit.\n");
return 0;
});
}
public:
//禁止拷贝和移动
FTimerEvent(const FTimerEvent&) = delete;
FTimerEvent& operator=(const FTimerEvent&) = delete;
//默认的构造函数
FTimerEvent(){ m_bExit = false; };
//带参数的构造函数
template<class F, class... Args>
FTimerEvent(uint32_t dwTimeout, F&& f, Args&&... args)
{
m_bExit = false;
m_funCallback = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
_InitTimer(dwTimeout);
}
//如果使用默认构造函数定义的示例 可以手动初始化 不允许重复调用
template<class F, class... Args>
bool InitTimer(uint32_t dwTimeout, F&& f, Args&&... args)
{
assert(m_funCallback == nullptr);
if (m_funCallback != nullptr)
return false;
m_funCallback = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
_InitTimer(dwTimeout);
return true;
}
~FTimerEvent(void)
{
StopTimer();
printf("Timer has Stopped. \n");
}
//阻塞事件,会等所有的回调都完成后再退出
//如果在回调内部调用,会立即返回
void StopTimer()
{
if (!m_bExit)
printf("Stop Timer \n");
//stop flag
m_bExit = true;
//通知一下阻塞事件
if (std::this_thread::get_id() != m_loopThreadID)
{
m_Condition.notify_one();
//等待线程退出
try
{
m_loopTask.get();
}
catch (...){}
}
}
//触发一次事件 异步返回
//必然触发的回调,哪怕调用了StopTimer也会把Set过的次数都回调一遍再退出
void SetTimerEvent()
{
m_nManual++;
m_Condition.notify_one();
}
};