任務線程池的封裝

Semaphore.h

#pragma once
#include <mutex>
#include <condition_variable>
#include <atomic>

namespace ASYN_WORK_NVR
{
    class Semaphore
    {
    public:
	   Semaphore();
	   ~Semaphore();
    public:
	   void Wait();
	   void Signal();
    private:
	   std::condition_variable condition;
	   std::mutex mutex;
	   unsigned int wakeups;
	   std::atomic<int> count;
    };
}

Semaphore.cpp

#include "Semaphore.h"

namespace ASYN_WORK_NVR
{
    Semaphore::Semaphore()
	   :count(0)
	   , wakeups(0)
    {
    }

    Semaphore::~Semaphore()
    {
    }

    void Semaphore::Wait()
    {
	   if (--count < 0)
	   {
		  std::unique_lock<std::mutex> lock(mutex);
		  condition.wait(lock, [&](){ return wakeups > 0; });
		  --wakeups;
	   }
    }

    void Semaphore::Signal()
    {
	   if (++count < 1)
	   {
		  std::unique_lock<std::mutex> lock(mutex);
		  ++wakeups;
		  condition.notify_one();
	   }
    }
}

Task.h

#pragma once

namespace ASYN_WORK_NVR
{
    class CTask
    {
    public:
	   CTask(void);
	   virtual ~CTask(void);
	   virtual void Do();
	   virtual void Cancel();
    };
}

Task.cpp

#include "Task.h"

namespace ASYN_WORK_NVR
{
    CTask::CTask(void) {}

    CTask::~CTask(void){}

    void CTask::Do(){}

    void CTask::Cancel(){}
}

TaskProxy.h

#pragma once
#include <mutex>
#include <thread>
#include <chrono>
#include <functional>
#include "Task.h"

namespace ASYN_WORK_NVR
{
    class CTaskProxy : public CTask
    {
    public:
	   CTaskProxy(const std::function<void()>& fn);
	   ~CTaskProxy();
    public:
	   void Control(bool canWork);
	   void Do()override;
	   void Cancel()override;
    private:
	   std::function<void()> m_fn;
	   bool m_canWork;
	   std::mutex m_mutexWork;
    };
}

TaskProxy.cpp

#include "TaskProxy.h"

namespace ASYN_WORK_NVR
{
    CTaskProxy::CTaskProxy(const std::function<void()>& fn)
	   :m_fn(fn)
	   , m_canWork(true)
    {
    }

    CTaskProxy::~CTaskProxy()
    {
    }

    void CTaskProxy::Control(bool canWork)
    {
	   std::unique_lock<std::mutex> lock(m_mutexWork);
	   m_canWork = canWork;
    }

    void CTaskProxy::Do()
    {
	   std::unique_lock<std::mutex> lock(m_mutexWork);
	   if (!m_canWork)
	   {
		  return;
	   }

	   if (m_fn)
	   {
		  m_fn();//不要在m_fn裏面調用Control
	   }
    }

    void CTaskProxy::Cancel()
    {
	   Do();
    }
}

TaskQueue.h

#pragma once
#include <queue>
#include <mutex>

namespace ASYN_WORK_NVR
{

    template<typename T>
    class CTaskQueue
    {
    public:
	   CTaskQueue(void){}
	   ~CTaskQueue(void){}
    public:
	   void Push(const T& t)
	   {
		  std::unique_lock<std::mutex> lock(m_mutexTask);
		  m_queueTask.push(t);
	   }

	   bool Front(T& t)
	   {
		  std::unique_lock<std::mutex> lock(m_mutexTask);
		  if (!m_queueTask.empty())
		  {
			 t = m_queueTask.front();
			 return true;
		  }
		  return false;
	   }

	   bool Pop(T& t)
	   {
		  std::unique_lock<std::mutex> lock(m_mutexTask);
		  if (!m_queueTask.empty())
		  {
			 t = m_queueTask.front();
			 m_queueTask.pop();
			 return true;
		  }
		  return false;
	   }

	   void Swap(std::queue<T>& queueTask)
	   {
		  std::unique_lock<std::mutex> lock(m_mutexTask);
		  m_queueTask.swap(queueTask);
	   }

	   unsigned int Size()
	   {
		  std::unique_lock<std::mutex> lock(m_mutexTask);
		  return m_queueTask.size();
	   }
    private:
	   std::queue<T> m_queueTask;
	   std::mutex m_mutexTask;
    };
}

ThreadPool.h

#pragma once
#include <memory>
#include <thread>
#include <mutex>
#include <vector>
#include "Task.h"
#include "TaskQueue.h"
#include "Semaphore.h"

namespace ASYN_WORK_NVR
{
    class CThreadPool
    {
    public:
	   CThreadPool(unsigned int num);
	   ~CThreadPool();
	   void PostTask(const std::shared_ptr<CTask>& pTask);
    private:
	   void Run(void);
	   void DoTask();
	   void Cancel();
    private:
	   CTaskQueue<std::shared_ptr<CTask> > m_TaskQueue;
	   Semaphore m_workSemaphore;
	   bool m_bExit;
	   std::vector<std::thread*> m_vecThread;
    };
}

ThreadPool.cpp

#include "ThreadPool.h"
#include <algorithm>
#include "INFCoreDll.h"
#include "Common.h"
#ifdef WIN32
#include <windows.h>
#else
#include <sys/time.h>

namespace ASYN_WORK_NVR
{
	const unsigned int DEFAULT_POOL_TIME = 20;  //ms

    CThreadPool::CThreadPool(unsigned int num)
	   :m_bExit(false)
    {
	   while (num--)
	   {
		  m_vecThread.push_back(new std::thread(std::bind(&CThreadPool::Run, this)));
	   }
    }

    CThreadPool::~CThreadPool()
    {
	   m_bExit = true;

	   for (int i = 0; i < m_vecThread.size(); i++)
	   {
		  m_workSemaphore.Signal();
	   }

	   std::for_each(m_vecThread.begin(), m_vecThread.end(), [&](std::thread* pThread)
	   {
		  if (pThread)
		  {
			 pThread->join();
			 delete pThread;
		  }
	   });
    }

    void CThreadPool::Run(void)
    {
	   while (!m_bExit)
	   {
		  m_workSemaphore.Wait();
		  DoTask();
	   }
	   Cancel();
    }

    void CThreadPool::DoTask()
    {
	   std::shared_ptr<CTask> pTask = nullptr;
	   
	   int queSize = m_TaskQueue.Size();
	   if (queSize > 10)
	   {
		   INFLOG_DBG(M_NVR_X, "CThreadPool::DoTask(), queue size is %03d(>10), for performance.", m_TaskQueue.Size());
	   }

	   while (m_TaskQueue.Pop(pTask))
	   {
		  if (pTask)
		  {
			 pTask->Do();
		  }

		  if (m_bExit)
		  {
			  INFLOG_DBG(M_NVR_X, "thread pool exit, queue size is %03d.", queSize - 1);
			 break;
		  }

		  queSize--;
		  int iMS = queSize < 5 ? DEFAULT_POOL_TIME : (queSize < 10 ? (DEFAULT_POOL_TIME + 10) : (DEFAULT_POOL_TIME + 20));
		  #ifdef WIN32
	      Sleep(iMS);
		  #else
	      usleep(iMS*1000);
          #endif
		  _UTILITY::SleepMS();//performance-def
	   }
    }

    void CThreadPool::Cancel()
    {
	   std::shared_ptr<CTask> pTask = nullptr;
	   while (m_TaskQueue.Pop(pTask))
	   {
		  if (pTask)
		  {
			 pTask->Cancel();
		  }
	   }
    }

    void CThreadPool::PostTask(const std::shared_ptr<CTask>& pTask)
    {
	   if (pTask)
	   {
		  m_TaskQueue.Push(pTask);
		  m_workSemaphore.Signal();
	   }
    }
}

main.cpp

#include "ThreadPool.h"
#include<iostream>

class CCMSConnecterTask : public ASYN_WORK_NVR::CTask
{
public:
    CCMSConnecterTask(){};
    ~CCMSConnecterTask(){};

    void Do()
    {	
    //消息處理
		std::cout << "do job" << std::endl;
	};
    void Cancel()
    {
    	Do();
    };
};


int main(void)
{	
	ASYN_WORK_NVR::CThreadPool* m_pHandlerThreadPool = nullptr;
	m_pHandlerThreadPool = new ASYN_WORK_NVR::CThreadPool(8);//線程池創建8個線程
	
	if (m_pHandlerThreadPool)
    {
	   std::shared_ptr<CCMSConnecterTask> pTask(new CCMSConnecterTask());
	   m_pHandlerThreadPool->PostTask(pTask); //執行任務
    }

	if (m_pHandlerThreadPool)
	{
		delete m_pHandlerThreadPool;
		m_pHandlerThreadPool = nullptr;
	}
	return 0;
}
發佈了56 篇原創文章 · 獲贊 18 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章