結合boost庫實現的定時任務類
WorkEvent.h
#pragma once
#include <mutex>
#include <condition_variable>
namespace ASYN_WORK_NVR
{
class CWorkEvent
{
public:
CWorkEvent();
~CWorkEvent();
public:
void SetEvent();
void WaitEvent();
void WaitEvent(const long long llTime);//ms,<0爲一直等
void ResetEvent();
private:
std::condition_variable m_conditionWake;
std::mutex m_mutexWake;
bool m_bWake;
};
}
WorkEvent.cpp
#include <chrono>
#include "WorkEvent.h"
namespace ASYN_WORK_NVR
{
CWorkEvent::CWorkEvent()
:m_bWake(false)
{
}
CWorkEvent::~CWorkEvent()
{
}
void CWorkEvent::SetEvent()
{
std::unique_lock<std::mutex> lock(m_mutexWake);
if (!m_bWake)
{
m_bWake = true;
m_conditionWake.notify_one();
}
}
void CWorkEvent::WaitEvent()
{
std::unique_lock<std::mutex> lock(m_mutexWake);
m_conditionWake.wait(lock, [&](){ return m_bWake; });
m_bWake = false;
}
void CWorkEvent::WaitEvent(const long long llTime)
{
if (llTime < 0)
{
WaitEvent();
}
else
{
std::unique_lock<std::mutex> lock(m_mutexWake);
if (m_conditionWake.wait_for(lock, std::chrono::milliseconds(llTime), [&](){ return m_bWake; }))
{
m_bWake = false;
}
}
}
void CWorkEvent::ResetEvent()
{
std::unique_lock<std::mutex> lock(m_mutexWake);
m_bWake = false;
}
}
Timer.h
#pragma once
#include <thread>
#include <mutex>
#include <functional>
#include <chrono>
#include "boost/chrono.hpp" //需引用boost庫的chrono.hpp
#include <vector>
#include "WorkEvent.h"
namespace ASYN_WORK_NVR
{
class CTimer
{
public:
typedef std::function<void()> fn;
CTimer();
~CTimer();
public:
void Start(const unsigned long long gaps, const fn& f);
void Stop();
private:
static void Init();
static void UnInit();
static void Run();
static bool GetMinGaps(unsigned long long& gaps);
private:
static std::mutex m_mutexTimer;
static std::vector<CTimer*> m_vecTimer;
static std::thread* m_pThread;
static bool m_bExit;
static CWorkEvent m_event;
static unsigned long long m_ref;
static std::mutex m_mutexRef;
private:
unsigned long long Check();
private:
boost::chrono::time_point<boost::chrono::steady_clock> m_lastClock; //boost庫的chrono.hpp
unsigned long long m_gaps;
fn m_f;
};
}
Timer.cpp
#include "Timer.h"
#include <algorithm>
namespace ASYN_WORK_NVR
{
std::mutex CTimer::m_mutexTimer;
std::vector<CTimer*> CTimer::m_vecTimer;
std::thread* CTimer::m_pThread = nullptr;
bool CTimer::m_bExit = false;
CWorkEvent CTimer::m_event;
unsigned long long CTimer::m_ref = 0;
std::mutex CTimer::m_mutexRef;
CTimer::CTimer()
:m_lastClock(boost::chrono::steady_clock::now())
, m_gaps(1)
, m_f(nullptr)
{
CTimer::Init();
}
CTimer::~CTimer()
{
CTimer::UnInit();
}
void CTimer::Init()
{
std::unique_lock<std::mutex> lock(m_mutexRef);
m_ref++;
if (1 == m_ref)
{
m_bExit = false;
m_pThread = new std::thread(CTimer::Run);
}
}
void CTimer::UnInit()
{
std::unique_lock<std::mutex> lock(m_mutexRef);
m_ref--;
if (0 == m_ref)
{
m_bExit = true;
m_event.SetEvent();
if (m_pThread)
{
m_pThread->join();
delete m_pThread;
m_pThread = nullptr;
}
}
}
void CTimer::Run()
{
while (!m_bExit)
{
unsigned long long llMinDelay = 0;
if (GetMinGaps(llMinDelay))
{
m_event.WaitEvent(llMinDelay);
}
else
{
m_event.WaitEvent();
}
}
}
bool CTimer::GetMinGaps(unsigned long long& gaps)
{
std::unique_lock<std::mutex> lock(m_mutexTimer);
if (m_vecTimer.size() > 0)
{
gaps = m_vecTimer[0]->Check();
for (int i = 1; i < m_vecTimer.size(); i++)
{
auto tmp = m_vecTimer[i]->Check();
if (tmp < gaps)
{
gaps = tmp;
}
}
return true;
}
return false;
}
void CTimer::Start(const unsigned long long gaps, const fn& f)
{
m_gaps = gaps;
m_f = f;
m_lastClock = boost::chrono::steady_clock::now();
{
std::unique_lock<std::mutex> lock(m_mutexTimer);
m_vecTimer.push_back(this);
}
m_event.SetEvent();
}
void CTimer::Stop()
{
std::unique_lock<std::mutex> lock(m_mutexTimer);
for (auto it = m_vecTimer.begin(); it != m_vecTimer.end(); it++)
{
if ((*it) == this)
{
m_vecTimer.erase(it);
return;
}
}
}
unsigned long long CTimer::Check()
{
long long gaps = boost::chrono::duration_cast<boost::chrono::milliseconds>(boost::chrono::steady_clock::now() - m_lastClock).count();
if (gaps >= m_gaps)
{
if (m_f)
{
m_f();
}
m_lastClock = boost::chrono::steady_clock::now();
return m_gaps;
}
else
{
return (m_gaps - gaps);
}
}
}
main.cpp
#include<memory>
#include<iostream>
#include<functional>
#include"Timer.h"
void Test()
{
std::cout << "hello !!" << std::endl;
}
int main()
{
std::shared_ptr<ASYN_WORK_NVR::CTimer> pThreadTimerWorker
pThreadTimerWorker = std::make_shared<ASYN_WORK_NVR::CTimer>();
pThreadTimerWorker->Start(1000 * 60, std::bind(&Test));//1分鐘執行一次Test
if (pThreadTimerWorker) //停止定時任務
{
pThreadTimerWorker->Stop();
pThreadTimerWorker = nullptr;
}
return 0;
}