c++ 定时器(多媒体定时器, posix定时器)

项目地址#

使用范例#

接口使用顺序#

  • 1 调用 init_
  • 2 启动定时器 begin_
  • 3 停止定时器 end_

ITimerPP类接口#

Copy Highlighter-hljs
class ITimerPP { public: using uint = unsigned int; enum TimerType { /// 单次执行 TIMER_TYPE_ONE_SHORT = 0, /// 周期执行 TIMER_TYPE_PERIODIC = 1, }; public: virtual ~ITimerPP() { } virtual int init_(const TimerType&& tt, ITimerCallBack* pcb) = 0; virtual int begin_(const uint&& interval_ms) = 0; virtual int end_() = 0; };

实现超时处理函数即可#

Copy Highlighter-hljs
class demoTimerCallback : public oct_tk::ITimerCallBack { public: virtual void timer_call_back_() { static int index = 0; std::cout << "\n index=" << ++index << "="; } };

创建定时器#

Copy Highlighter-hljs
demoTimerCallback tc; std::unique_ptr<ITimerPP> demo_timer = oct_tk::new_itimer_(); ITimerPP* ptimer = demo_timer.get(); ptimer->init_(oct_tk::ITimerPP::TIMER_TYPE_PERIODIC, &tc); ptimer->begin_(40); std::this_thread::sleep_for(std::chrono::seconds(1 * 30)); ptimer->end_();

NOTE#

  • 完整范例可在项目中 example中 main.cc中获取

更新日志#

  • 2023-03-11
    • 重新封装windows多媒体定时器。 完整代码如下(copy即可使用)

TimerImp.h#

Copy Highlighter-hljs
#ifndef TIMER_IMP_H_ #define TIMER_IMP_H_ #include <functional> #include <string> #include <atomic> namespace oct_tm { class NonCopyable { protected: NonCopyable() {} virtual ~NonCopyable() {} private: NonCopyable(const NonCopyable&); NonCopyable& operator=(const NonCopyable&); }; /// ---------------------------------------------------------------------------------------- /// @brief: 定时器类型 /// ---------------------------------------------------------------------------------------- enum TIMERT_TYPE { /// 周期执行, TT_PERIOD = 1, /// 单次触发, 回调函数在定时器启动后仅执行一次 TT_ONE_SHOT = 0, }; /// 定时器回调函数, 函数参数: 定时器ID using OnTimeoutFunc = std::function<void(const unsigned int)>; /// ---------------------------------------------------------------------------------------- /// @brief: 多媒体定时器封装 /// timeBeginPeriod: win7下全局设置精度; 而win10 2004非全局精度设置 /// ---------------------------------------------------------------------------------------- class TimerImp : public NonCopyable { public: TimerImp(); ~TimerImp(); /// ------------------------------------------------------------------------------- /// @brief: 初始化 /// @param: const TIMERT_TYPE timer_type - 定时器类型 /// @param: OnTimeoutFunc cb - 超时执行函数 /// @ret: int /// 0 - 成功 /// != 0 - 失败, lastError 获取 错误 /// ------------------------------------------------------------------------------- int init(const TIMERT_TYPE timer_type, OnTimeoutFunc cb); /// ------------------------------------------------------------------------------- /// @brief: 开启定时器 /// @param: const unsigned int interval_ms - 定时器周期,单位:ms /// @ret: int /// 0 - 成功 /// != 0 - 失败, lastError 获取 错误 /// ------------------------------------------------------------------------------- int begin(const unsigned int interval_ms); /// ------------------------------------------------------------------------------- /// @brief: 停止定时器 /// @ret: int /// 0 - 成功 /// ------------------------------------------------------------------------------- int end(); /// ------------------------------------------------------------------------------- /// @brief: 获取最近一次的错误信息 /// @ret: std::string /// /// ------------------------------------------------------------------------------- std::string lastError(); /// ------------------------------------------------------------------------------- /// @brief: 获取当前设定的定时器精度 /// @ret: unsigned int /// /// ------------------------------------------------------------------------------- unsigned int timerPrecision() const; /// ------------------------------------------------------------------------------- /// @brief: 获取定时器是否准备好 /// @ret: bool /// /// ------------------------------------------------------------------------------- bool timerPrepared() const; private: static void CALLBACK TimeProc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2); private: /// 超时执行函数s OnTimeoutFunc timeout_func_ = nullptr; /// 错误信息 std::string error_msg_{}; /// 定时器类型 int timer_type_ = TT_ONE_SHOT; /// 获取 std::atomic_bool prepare_timer_ = false; /// 定时器精度 std::atomic_uint timer_precision_ = 1; /// 定时器ID unsigned int timer_id_ = 0; }; } #endif ///!TIMER_IMP_H_

Timer.cpp#

Copy Highlighter-hljs
#include <Mmsystem.h> #include "TimerImp.h" #pragma comment(lib, "Winmm.lib") namespace oct_tm { /// -------------------------------------------------------------------------------- /// @brief: TimerImp::TimerImp /// -------------------------------------------------------------------------------- TimerImp::TimerImp() { TIMECAPS tc; if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { error_msg_ = std::string("call [timeGetDevCaps] function error"); prepare_timer_ = false; } else { timer_precision_ = min((tc.wPeriodMin, 1), tc.wPeriodMax); timeBeginPeriod(timer_precision_); prepare_timer_ = true; } } /// -------------------------------------------------------------------------------- /// @brief: TimerImp::~TimerImp /// -------------------------------------------------------------------------------- TimerImp::~TimerImp() { if (true == prepare_timer_) { end(); timeEndPeriod(timer_precision_); } } /// -------------------------------------------------------------------------------- /// @brief: TimerImp::init /// -------------------------------------------------------------------------------- int TimerImp::init(const TIMERT_TYPE timer_type, OnTimeoutFunc cb) { if (false == prepare_timer_) { return 3; } if ((TT_PERIOD != timer_type) && (TT_ONE_SHOT != timer_type)) { error_msg_ = std::string("the timer_type parameter is false"); return 1; } if (nullptr == cb) { error_msg_ = std::string("the cb parameter is empty"); return 2; } timer_type_ = timer_type; timeout_func_ = std::move(cb); return 0; } /// -------------------------------------------------------------------------------- /// @brief: TimerImp::begin /// -------------------------------------------------------------------------------- int TimerImp::begin(const unsigned int interval_ms) { if (false == prepare_timer_) { return 3; } if (0 == interval_ms) { error_msg_ = std::string("the interval_ms parameter cannot be zero"); return 1; } end(); /// 2. 启动定时器 if (NULL == (timer_id_ = timeSetEvent(interval_ms, NULL, TimeProc, (DWORD_PTR)this, static_cast<int>(timer_type_)))) { error_msg_ = std::string("failed to create timer"); return 2; } return 0; } /// -------------------------------------------------------------------------------- /// @brief: TimerImp::end /// -------------------------------------------------------------------------------- int TimerImp::end() { if (0 != timer_id_) { timeKillEvent(timer_id_); timer_id_ = 0; } return 0; } /// -------------------------------------------------------------------------------- /// @brief: 获取最近一次的错误信息 /// -------------------------------------------------------------------------------- std::string TimerImp::lastError() { std::string ret = error_msg_; error_msg_ = std::string{}; return ret; } /// -------------------------------------------------------------------------------- /// @brief: 获取当前设定的定时器精度 /// -------------------------------------------------------------------------------- unsigned int TimerImp::timerPrecision() const { return timer_precision_; } /// -------------------------------------------------------------------------------- /// @brief: TimerImp::timerPrepared /// -------------------------------------------------------------------------------- bool TimerImp::timerPrepared() const { return prepare_timer_; } /// -------------------------------------------------------------------------------- /// @brief: TimerImp::TimeProc /// -------------------------------------------------------------------------------- void CALLBACK TimerImp::TimeProc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) { TimerImp* pimp = (TimerImp*)(dwUser); if (pimp) { if (pimp->timeout_func_) { pimp->timeout_func_(pimp->timer_id_); } } } }

使用范例#

  • 使用步骤:
    • 1 设置超时函数
    • 2 初始化 init
    • 3 启动定时器 begin
    • 5 停止定时器 end

如果如果初始化返回错误, 调用 lastError 函数即可。

Copy Highlighter-hljs
oct_tm::TimerImp timer_pp_; // 设置超时函数 auto timeout_func = std::bind(&CMFCApplication1Dlg::timerTimeoutFunc, this, std::placeholders::_1); timer_pp_.init(oct_tm::TT_PERIOD, timeout_func); // 启动定时器: 40ms timer_pp_.begin(40); // 停止定时器 timer_pp_.end(); // 获取错误信息 std::string error_str = timer_pp_.lastError();
  • 其中, CMFCApplication1Dlg::timerTimeoutFunc 函数定义如下
Copy Highlighter-hljs
/// ------------------------------------------------------------------------------- /// @brief: 定时器回调函数 /// @param: const unsigned int timer_id - 定时器ID /// @ret: void /// /// ------------------------------------------------------------------------------- void timerTimeoutFunc(const unsigned int timer_id);
posted @   mohist  阅读(1810)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· Open-Sora 2.0 重磅开源!
点击右上角即可分享
微信分享提示
CONTENTS