源码链接:https://github.com/SaberMqd/naive/blob/master/include/naive/work_thread/work_thread.h
原理:
new thread( //开启一个线程
while(true){ //无限循环
wait(task) 等待任务
if(over){ //是否结束,结束则退出循环
break;
}
task.do() //执行任务
}
).detach()
附源码:
#ifndef _NAIVE_WORK_TASK_H_
#define _NAIVE_WORK_TASK_H_
namespace naive {
struct WorkTask {
explicit WorkTask() {}
virtual ~WorkTask() {}
virtual bool Process() = 0;
};
}
#endif // !_NAIVE_WORK_TASK_H_
#ifndef _NAIVE_WORK_THREAD_H_
#define _NAIVE_WORK_THREAD_H_
#include "single_work_thread.h"
#include "ring_object_buffer.h"
#include "base_constructor.h"
#include "work_task.h"
#include <map>
#include <shared_mutex>
namespace naive {
#define WPM_CREATE_WORK naive::WorkThreadManager::GetInstance()->CreateWrokThread
#define WPM_GET_WORK(x) naive::WorkThreadManager::GetInstance()->GetWrokThread(x)
#define WPM_DELETE_WORK(x) naive::WorkThreadManager::GetInstance()->DeleteWorkThread(x)
template <class Closure>
class ClosureTask : public WorkTask {
public:
explicit ClosureTask(const Closure& closure) : _closure(closure) {}
bool Process() override {
_closure();
return true;
}
Closure _closure;
};
class WorkThreadManager;
class WorkThread
{
public:
explicit WorkThread(uint32_t id) :
_maxAsyncBufSize(48),
_tp(SingleWorkThread::Create()),
_runing(false),
_id(id),
_asyncBuf(nullptr){
}
void SetMaxTaskNum(uint32_t count) {
_maxAsyncBufSize = count;
}
void Reset() {
_smtx.lock();
_asyncBuf->Reset();
_smtx.unlock();
}
void Run() {
if (_runing) {
return;
}
_runing = true;
_asyncBuf = new RingObjBuf<WorkTask>(_maxAsyncBufSize);
_tp->Run([this] {
std::unique_ptr<WorkTask> task;
_smtx.lock_shared();
bool ret = _asyncBuf->Pop(task);
_smtx.unlock_shared();
if (ret && task.get()) {
return task->Process();
}
return true;
});
}
template <class WorkTask>
int PostTask(std::unique_ptr<WorkTask> task) {
if (!_runing) {
return -1;
}
std::lock_guard<std::mutex> lck(_mtx);
_smtx.lock_shared();
bool ret = _asyncBuf->Push(std::move(task));
_smtx.unlock_shared();
if (!ret) {
return -1;
}
_tp->Notify();
return 0;
}
template <class Closure>
void PostTask(const Closure& closure) {
PostTask(std::move(std::unique_ptr<WorkTask>(new ClosureTask<Closure>(closure))));
}
void Stop() {
if (_tp) {
_tp->Stop();
}
}
private:
friend WorkThreadManager;
~WorkThread() {
Stop();
SafeDelete(_tp);
SafeDelete(_asyncBuf);
}
std::mutex _mtx;
std::shared_mutex _smtx;
SingleWorkThread *_tp;
RingObjBuf<WorkTask> *_asyncBuf;
bool _runing;
uint32_t _maxAsyncBufSize;
uint32_t _id;
DISALLOW_COPY_AND_ASSIGN(WorkThread);
};
class WorkThreadManager
{
public:
static WorkThreadManager* GetInstance() {
static WorkThreadManager t;
return &t;
};
WorkThreadManager() : _id(0) {}
~WorkThreadManager() {
for (auto &v : _wts) {
delete v.second;
v.second = nullptr;
}
_wts.clear();
}
uint32_t CreateWrokThread() {
std::unique_lock<std::mutex> lck(_mtx);
_id++;
_wts[_id] = new WorkThread(_id);
return _id;
}
void DeleteWorkThread(uint32_t id) {
std::unique_lock<std::mutex> lck(_mtx);
auto th = _wts.find(id);
if (th == _wts.end()) {
return;
}
delete th->second;
_wts.erase(id);
}
WorkThread* GetWrokThread(uint32_t id) {
std::unique_lock<std::mutex> lck(_mtx);
if (_wts.find(id) != _wts.end()) {
return _wts[id];
}
return nullptr;
}
private:
uint32_t _id;
std::mutex _mtx;
std::map<uint32_t, WorkThread*> _wts;
DISALLOW_COPY_AND_ASSIGN(WorkThreadManager);
};
}
#endif // !_NAIVE_WORK_THREAD_H_
#ifndef _NAIVE_SINGLE_WORK_THREAD_H_
#define _NAIVE_SINGLE_WORK_THREAD_H_
#include <functional>
#include <string>
namespace naive {
class SingleWorkThread {
public:
static SingleWorkThread* Create();
virtual void Run(std::function<bool()>) = 0;
virtual void Notify() = 0;
virtual void Stop() = 0;
virtual void SetID(const std::string &id) = 0;
virtual const std::string& GetID() const = 0;
virtual ~SingleWorkThread() {}
protected:
SingleWorkThread() {}
};
}
#endif // !_NAIVE_SINGLE_WORK_THREAD_H_
#ifndef _NAIVE_THREAD_PROCESSOR_RELIABLE_H_
#define _NAIVE_THREAD_PROCESSOR_RELIABLE_H_
#include "naive/work_thread/single_work_thread.h"
#include "naive/base_constructor.h"
#include "naive/safe_wait.h"
#include <mutex>
#include <thread>
#include <atomic>
namespace naive {
class SingleWorkThreadImpl : public SingleWorkThread {
public:
explicit SingleWorkThreadImpl();
void Run(std::function<bool()> func) override;
void Notify() override;
void Stop() override;
void SetID(const std::string &id) override;
const std::string& GetID() const override;
~SingleWorkThreadImpl();
private:
std::thread *_thread;
std::function<bool()> _func;
bool _shouldStop;
bool _threadOver;
bool _inited;
std::atomic<bool> _isRuning;
std::atomic<bool> _isBusy;
std::mutex _mtx;
SafeConditionVariable _scv;
SafeConditionVariable _endScv;
std::string _id;
DISALLOW_COPY_AND_ASSIGN(SingleWorkThreadImpl);
};
}
#endif // !_NAIVE_THREAD_PROCESSOR_RELIABLE_H_
#include "single_work_thread_impl.h"
#include "naive/safe_delete.h"
namespace naive {
SingleWorkThread* SingleWorkThread::Create() {
return new SingleWorkThreadImpl();
}
SingleWorkThreadImpl::SingleWorkThreadImpl():
_thread(nullptr),
_func(nullptr),
_threadOver(false),
_shouldStop(false),
_isRuning(false),
_isBusy(false),
_inited(false){
}
SingleWorkThreadImpl::~SingleWorkThreadImpl(){
Stop();
SafeDelete(_thread);
}
void SingleWorkThreadImpl::Run(std::function<bool()> func) {
std::unique_lock<std::mutex> lg(_mtx);
if (_inited) {
return;
}
_inited = true;
_func = func;
_isRuning = true;
_thread = new std::thread([this]() {
while (true) {
_scv.Wait();
if (_shouldStop) {
break;
}
if (!_func()) {
break;
}
}
_endScv.Notify();
});
_thread->detach();
}
void SingleWorkThreadImpl::Notify() {
_scv.Notify();
}
void SingleWorkThreadImpl::Stop() {
std::unique_lock<std::mutex> lg(_mtx);
if (!_isRuning) {
return;
}
_shouldStop = true;
_scv.Notify();
_endScv.Wait();
_isRuning = false;
}
void SingleWorkThreadImpl::SetID(const std::string &id) {
_id = id;
}
const std::string& SingleWorkThreadImpl::GetID() const {
return _id;
}
}
example:
#include "test.h"
void TestWorkThread() {
auto wid = WPM_CREATE_WORK();
auto wth = WPM_GET_WORK(wid);
if (wth) {
wth->SetMaxTaskNum(24);
wth->Run();
auto task = [wid] { NE("work thread id is %d", wid); };
for (int i = 0; i < 10; ++i) {
wth->PostTask(task);
}
}
WPM_DELETE_WORK(wid);
_sleep(2 * 1000);
}