Task.h
namespace ASYN_WORK
{
class CTask
{
public:
CTask(void);
virtual ~CTask(void);
virtual void Do();
virtual void Cancel();
};
}
Task.cpp
#include "Task.h"
namespace ASYN_WORK
{
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
{
class CTaskProxy : public CTask
{
public:
CTaskProxy(const std::function<void()>& fn);
void Do()override;
void Cancel()override;
void CancelWithoutDoTask();
~CTaskProxy();
public:
void Control(bool canWork);
private:
std::function<void()> m_fn;
std::mutex m_mutexWork;
bool m_canWork;
bool m_cancelWithoutDoTask;
};
}
TaskProxy.cpp
#include "TaskProxy.h"
namespace ASYN_WORK
{
CTaskProxy::CTaskProxy(const std::function<void()>& fn)
:m_fn(fn)
, m_canWork(true)
, m_cancelWithoutDoTask(false)
{
}
CTaskProxy::~CTaskProxy()
{
}
void CTaskProxy::CancelWithoutDoTask()
{
m_cancelWithoutDoTask = true;
}
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()
{
if (!m_cancelWithoutDoTask)
{
Do();
}
}
}
TaskQueue.h
#pragma once
#include <queue>
#include <mutex>
namespace ASYN_WORK
{
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 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;
};
}
WorkEvent.h
#pragma once
#include <mutex>
#include <condition_variable>
namespace ASYN_WORK
{
class CWorkEvent
{
public:
CWorkEvent();
~CWorkEvent();
public:
void SetEvent();
void WaitEvent();
void WaitEvent(const unsigned long long llTime);//ms
void ResetEvent();
private:
std::condition_variable m_conditionWake;
std::mutex m_mutexWake;
bool m_bWake;
};
}
WorkEvent.cpp
#include "WorkEvent.h"
namespace ASYN_WORK
{
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 unsigned long long llTime)
{
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;
}
}
Asyn_Thread.h
#pragma once
#include "WorkEvent.h"
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
namespace ASYN_WORK
{
class CThread
{
public:
CThread(void);
~CThread(void);
public:
virtual void Start();
virtual void Stop();
protected:
virtual void Run() = 0;
bool m_bExit;
CWorkEvent m_workEvent;
private:
std::thread* m_pThread;
};
}
Asyn_Thread.cpp
#include "Asyn_Thread.h"
#ifdef __linux__
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#endif
namespace ASYN_WORK
{
CThread::CThread(void)
:m_bExit(false)
, m_pThread(nullptr)
{
}
CThread::~CThread(void)
{
}
void CThread::Start()
{
m_bExit = false;
m_workEvent.ResetEvent();
m_pThread = new std::thread(std::bind(&CThread::Run, this));
#ifdef __linux__
auto handle = m_pThread->native_handle();
std::string tName = MODULE_NAME + std::string("CTh");
LOG_DEBUG("thread %d --- with name %s", handle, tName.c_str());
pthread_setname_np(handle, tName.c_str());
#endif
}
void CThread::Stop()
{
if (m_bExit)
{
return;
}
m_bExit = true;
m_workEvent.SetEvent();
if (m_pThread)
{
m_pThread->join();
delete m_pThread;
m_pThread = nullptr;
}
}
}
ThreadWorker.h
#pragma once
#include <memory>
#include "Asyn_Thread.h"
#include "Task.h"
#include "TaskQueue.h"
namespace ASYN_WORK
{
class CThreadWorker :
public ASYN_WORK::CThread
{
public:
CThreadWorker(void);
~CThreadWorker(void);
void PostTask(const std::shared_ptr<CTask>& pTask);
void DoTask();
private:
void Run(void);
void Cancel();
private:
std::queue<std::shared_ptr<CTask> > m_taskQueue;
CTaskQueue<std::shared_ptr<CTask> > m_incomingTaskQueue;
};
}
ThreadWorker.cpp
#include "ThreadWorker.h"
namespace ASYN_WORK
{
CThreadWorker::CThreadWorker(void)
{
}
CThreadWorker::~CThreadWorker(void)
{
CThread::Stop();
}
void CThreadWorker::Run(void)
{
while (!m_bExit)
{
m_workEvent.WaitEvent();
DoTask();
}
Cancel();
}
void CThreadWorker::DoTask()
{
m_incomingTaskQueue.Swap(m_taskQueue);
while (!m_taskQueue.empty())
{
std::shared_ptr<CTask> pTask = nullptr;
pTask = m_taskQueue.front();
m_taskQueue.pop();
if (pTask)
{
pTask->Do();
}
if (m_bExit)
{
break;
}
}
}
void CThreadWorker::Cancel()
{
std::shared_ptr<CTask> pTask = nullptr;
while (!m_taskQueue.empty())
{
pTask = m_taskQueue.front();
m_taskQueue.pop();
if (pTask)
{
pTask->Cancel();
}
}
while (m_incomingTaskQueue.Pop(pTask))
{
if (pTask)
{
pTask->Cancel();
}
}
}
void CThreadWorker::PostTask(const std::shared_ptr<CTask>& pTask)
{
if (pTask)
{
m_incomingTaskQueue.Push(pTask);
m_workEvent.SetEvent();
}
}
}
TaskHelper.h
#pragma once
#include "ThreadWorker.h"
#include <mutex>
using namespace std;
using namespace ASYN_WORK;
class TaskHelper
{
public:
TaskHelper();
~TaskHelper();
private:
static TaskHelper* _instance;
CThreadWorker* m_pThread;
static mutex m_mutex;
public:
static TaskHelper* Instance();
void PostTask(const std::shared_ptr<CTask>& pTask);
};
TaskHelper.cpp
#include "TaskHelper.h"
TaskHelper* TaskHelper::_instance = nullptr;
mutex TaskHelper::m_mutex;
TaskHelper::TaskHelper()
: m_pThread(nullptr)
{
m_pThread = new CThreadWorker();
m_pThread->Start();
}
TaskHelper::~TaskHelper()
{
if (m_pThread != nullptr)
{
delete m_pThread;
m_pThread = nullptr;
}
}
TaskHelper* TaskHelper::Instance()
{
unique_lock<mutex> lock(m_mutex);
if (_instance == nullptr)
{
_instance = new TaskHelper();
}
return _instance;
}
void TaskHelper::PostTask(const std::shared_ptr<CTask>& pTask)
{
if (m_pThread != nullptr)
{
m_pThread->PostTask(pTask);
}
}
main.cpp
#include "TaskProxy.h"
#include "TaskHelper.h"
#include<iostream>
void DoJob()
{
std::cout << "Do job" << std::endl;
return;
}
int main(void)
{
shared_ptr<CTaskProxy> m_taskProxy;
m_taskProxy = std::make_shared<ASYN_WORK::CTaskProxy>(std::bind(&DoJob));
TaskHelper::Instance()->PostTask(m_taskProxy);
m_taskProxy->Control(false);
return 0;
}