任务线程池的封装

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值