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