基于C++11的定时器类

#ifndef CBT_TIMER_H
#define CBT_TIMER_H
/***********************************************
*CBT_Timer
*description:定时器类
*
*created by y.y
*	2023/9/26
*回调函数定义:void timerCallBack(){...}
*用法说明:
*例1:CBT_Timer timer1(1000, timerCallBack);
*例2:CBT_Timer timer2;
*    timer2.InitTimer(1000, timerCallBack);
*定时器时间间隔参数单位:毫秒
***********************************************/
#include <thread>
#include <functional>
#include <chrono>
#include <future>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <assert.h>
#include <unistd.h>

class CBT_Timer;
typedef std::shared_ptr<CBT_Timer> CBT_TimerPtr;

class CBT_Timer
{
    friend class F;
public:
    CBT_Timer();
    ~CBT_Timer(void);

    //带参数的构造函数
    template<class F, class... Args>
    CBT_Timer(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;
    }

    //阻塞事件,会等所有的回调都完成后再退出
    //如果在回调内部调用,会立即返回
    void StopTimer();

    //触发一次事件 异步返回
    //必然触发的回调,哪怕调用了StopTimer也会把Set过的次数都回调一遍再退出
    void SetTimerEvent();

private:
       void _InitTimer(uint32_t nTimeout);

private:
    CBT_Timer(const CBT_Timer&) = delete;
    CBT_Timer& operator=(const CBT_Timer&) = delete;

    std::mutex                  m_mtx;
    std::condition_variable     m_Condition;
    std::future<int>            m_loopTask;                     //线程任务
    std::thread::id             m_loopThreadID;                 //线程ID
    std::function<void()>       m_funCallback;                  //回调函数
    bool                        m_bExit;                        //退出标记
    std::atomic<int>            m_nManual;
};
#endif // CBT_TIMER_H
/***********************************************
*CBT_Timer
*description:定时器类
*
*created by y.y
*	2023/9/26
*回调函数定义:void timerCallBack(){...}
*用法说明:
*例1:CBT_Timer timer1(1000, timerCallBack);
*例2:CBT_Timer timer2;
*    timer2.InitTimer(1000, timerCallBack);
*定时器时间间隔参数单位:毫秒
***********************************************/
#include "cbt_timer.h"

CBT_Timer::CBT_Timer()
{
    m_bExit = false;
}

CBT_Timer::~CBT_Timer()
{
    StopTimer();
}

void CBT_Timer::_InitTimer(uint32_t nTimeout)
{
    m_nManual = 0;

    m_loopTask = std::async(std::launch::async, [this, nTimeout]()->int
    {
        //时间线程启动
        m_loopThreadID = std::this_thread::get_id();

        while (!m_bExit || m_nManual)
        {
            //等待超时
            std::unique_lock<std::mutex> lock(m_mtx);

            if (nTimeout)
            {
                m_Condition.wait_for(lock, std::chrono::milliseconds(nTimeout), [this](){return (m_nManual != 0); });

                //调用回调函数
                m_funCallback();
            }
            else
                m_Condition.wait(lock, [this](){return (m_nManual != 0); });

            if (m_bExit && m_nManual == 0)
                return 0;

            if (m_nManual)
                m_nManual--;
        }

        //线程退出
        return 0;
    });
}

void CBT_Timer::StopTimer()
{
    if (!m_bExit)
        //停止计时器

    //修改停止标识
    m_bExit = true;

    //通知一下阻塞事件
    if (std::this_thread::get_id() != m_loopThreadID)
    {
        m_Condition.notify_one();

        //等待线程退出
        try
        {
            m_loopTask.get();
        }
        catch (...){}
    }
}

void CBT_Timer::SetTimerEvent()
{
    m_nManual++;
    m_Condition.notify_one();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值