定時任務類

結合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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章