BlackFeather'S Blog

首页 | |

C++11标准stl库的timer


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); }, &param);
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();
}

};


2020/9/7 | Tags:timer,定时器,std,stl | C/C++代码 | 查看评论(0)

Powered By Z-Blog  触屏版 | WAP版 | 电脑版