簡單的工作線程實現

源碼鏈接: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);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章