不到300行的简单线程池C++实现

/ 头文件 Thread.h//

/**************
	Multi-threading-related Classes
	
	2011-11-03 Add By AYA
		Support Windows platform only

 **************/
#ifndef THREAD_H_2011_11_03
#define THREAD_H_2011_11_03
#include <list>
#include <string>
#ifdef WIN32
#include <windows.h>
#endif


class ThreadException {
public:
	ThreadException (const char* msg) 
		: mMsg (msg) {
	}

	const char* what () const {
		return mMsg.c_str ();
	}
private:
	std::string mMsg;
};



/ Lock & LockGuide //
class Lock {
public:
	Lock ();
	~Lock ();

public:
	void Enter ();
	void Leave ();


private:
	CRITICAL_SECTION mSection;
};


class LockGuide {
public:
	LockGuide (Lock& _Lock)
		:mLock (_Lock) {
			mLock.Enter();
	}

	~LockGuide () {
		mLock.Leave ();
	}

private:
	Lock& mLock;
};


/// Signal ///
class Signal {
public:
	Signal ();
	~Signal ();

public:
	bool Wait (unsigned int Timeout = INFINITE);
	void WakeUp ();

private:
	HANDLE mHandle;
};


// Job /

class Job {
public:
	virtual void Do () = 0;
};



/ Thread ///
class Thread {
	friend class ThreadPool;
public:
	Thread (ThreadPool& Pool);
	virtual ~Thread ();

public:
	void Attach (Job* _Job);

private:
	/// Only called by ThreadPool
	void Die ();

private:
	static DWORD WINAPI Routine (LPVOID Parameter);

private:
	DWORD			mThreadID;
	HANDLE			mHandle;
	Lock			mLock;
	Signal			mSignal;
	Signal			mDieSignal;
	Job*			mCurrJob;
	ThreadPool&		mPool;
	bool			mIsDie;
};



/ ThreadPool /
class ThreadPool {
	friend class Thread;
public:
	ThreadPool ();
	~ThreadPool ();

public:
	bool Alloc (unsigned int ThreadNum);
	bool IsBusy ();
	void Release (); /// WARNING: ALL THREADS MUST BE IDLE BEFORE RELEASE THE POOL!
	Thread* Get ();
	

private:
	/// Only called by Thread
	void Put (Thread* _Thread);


private:
	Lock mKeeper;
	std::list<Thread*> mIdleThreads;
	std::list<Thread*> mBusyThreads;
};


#endif

/实现 Thread.cpp///

#include "Thread.h"

Lock::Lock()
{
	InitializeCriticalSection (&mSection);
}

Lock::~Lock()
{
	DeleteCriticalSection (&mSection);
}

void
Lock::Enter()
{
	EnterCriticalSection (&mSection);
}

void 
Lock::Leave()
{
	LeaveCriticalSection (&mSection);
}



#undef  _CLASS_
#define _CLASS_ "Signal"

Signal::Signal()
{
	mHandle = CreateSemaphore (NULL, 0, 1, NULL);
	if (!mHandle) {
		throw ThreadException ("CreateSemaphore Failed");
	}
}


Signal::~Signal()
{
	CloseHandle (mHandle);
}


bool 
Signal::Wait (eolas_uint Timeout)
{
	if (WAIT_OBJECT_0 != WaitForSingleObject(mHandle, Timeout)) {
		return false;
	}
	return true;
}


void
Signal::WakeUp ()
{
	if (!ReleaseSemaphore(mHandle, 1, NULL)) {
		throw ThreadException ("ReleaseSemaphore Failed");
	}
}




#undef  _CLASS_
#define _CLASS_ "Thread"


Thread::Thread(ThreadPool& Pool)
:mPool (Pool),
 mThreadID (0),
 mCurrJob (NULL),
 mIsDie (false)
{
	mHandle = CreateThread (
		NULL,
		0,
		Routine,
		this,
		0,
		&mThreadID
		);
	if (NULL == mHandle) {
		throw ThreadException ("CreateThread Failed");
	}
}

Thread::~Thread()
{
}


void 
Thread::Attach (Job* _Job)
{
	LockGuide Guide (mLock);

	mCurrJob = _Job;
	mSignal.WakeUp();
}


void 
Thread::Die()
{
	mLock.Enter();

	mIsDie = true;
	mSignal.WakeUp();
	mLock.Leave();
	mDieSignal.Wait();

}


DWORD 
Thread::Routine (LPVOID Parameter)
{
	Thread* _Thread = static_cast <Thread*> (Parameter);
	while (true) {
		_Thread->mSignal.Wait();

		/// 检查线程是否需要退出
		_Thread->mLock.Enter();
		if (_Thread->mIsDie) {
			_Thread->mLock.Leave();
			break;
		}
		_Thread->mLock.Leave();

		/// 干活
		_Thread->mCurrJob->Do();


		/// 干完活,回到IDLE状态
		_Thread->mLock.Enter();
		_Thread->mCurrJob = NULL;
		_Thread->mPool.Put (_Thread);
		_Thread->mLock.Leave();

	}

	_Thread->mDieSignal.WakeUp();
	return 0;
}




#undef  _CLASS_
#define _CLASS_ "ThreadPool"


ThreadPool::ThreadPool()
{
}

ThreadPool::~ThreadPool()
{
	Release();
}


bool 
ThreadPool::Alloc (unsigned int ThreadNum)
{
	LockGuide Guide(mKeeper);
	try {
		for (unsigned int N = 0; N < ThreadNum; ++N) {
			mIdleThreads.push_back(new Thread (*this));
		}
	} catch (const ThreadException& e) {
		return false;
	}
	return true;
}


void 
ThreadPool::Release()
{
	LockGuide Guide(mKeeper);

	/// 编程上的要求:
	/// 释放线程池之前必须先让所有Thread进入Idle状态
	/// 这样才不用强制Kill掉线程
	assert(mBusyThreads.empty());

	while (!mIdleThreads.empty()) {
		Thread* _Thread = mIdleThreads.front();
		_Thread->Die();
		delete _Thread;
		mIdleThreads.pop_front();
	}
}


Thread* 
ThreadPool::Get()
{
	LockGuide Guide (mKeeper);
	if (!mIdleThreads.empty()) {
		Thread* _Thread = mIdleThreads.front();
		mIdleThreads.pop_front();
		mBusyThreads.push_back(_Thread);
		return _Thread;
	}
	return NULL;
}


void 
ThreadPool::Put (Thread* _Thread)
{
	LockGuide Guide (mKeeper);
	mBusyThreads.remove(_Thread);
	mIdleThreads.push_back(_Thread);
}

bool 
ThreadPool::IsBusy()
{
	LockGuide Guide (mKeeper);
	return !mBusyThreads.empty();
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值