c++ 定时器(多媒体定时器, posix定时器)
项目地址
- CMAKE 管理项目
- windows使用的是: 多媒体定时器
- linux 使用的是: posix timer
- 地址: https://gitee.com/mohistH/timer-pp
- 需要c++11及以上支持
使用范例
接口使用顺序
- 1 调用 init_
- 2 启动定时器 begin_
- 3 停止定时器 end_
ITimerPP类接口
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;
};
实现超时处理函数即可
class demoTimerCallback : public oct_tk::ITimerCallBack
{
public:
virtual void timer_call_back_()
{
static int index = 0;
std::cout << "\n index=" << ++index << "=";
}
};
创建定时器
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
#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
#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 函数即可。
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 函数定义如下
/// -------------------------------------------------------------------------------
/// @brief: 定时器回调函数
/// @param: const unsigned int timer_id - 定时器ID
/// @ret: void
///
/// -------------------------------------------------------------------------------
void timerTimeoutFunc(const unsigned int timer_id);