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

项目地址

使用范例

接口使用顺序

  • 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);
posted @ 2022-06-21 21:57  mohist  阅读(1729)  评论(2编辑  收藏  举报