www.pudn.com > ThreadLibrary.zip > ThreadPool.h


/** 
 *	@file 
 */ 
#pragma once 
#include "ThreadRequest.h" 
#include "ManualEvent.h" 
#include "CriticalSection.h" 
#include "Semaphore.h" 
#include  
#include  
#include  
#include  
 
namespace 
{ 
const int THREAD_COUNT = 20;				///< Number of threads to initialize to start the requests 
const int MAX_QUEUE_SIZE = 100;				///< Maximum size of queue before submitJob blocks 
}; 
 
/**	 
 *	Creates a pool of threads, which will service a queue of funtors. 
 *  
 *	The pool of threads is determined by the MAX_THREADS define, or passed in through the constructor.    
 *  To have a thread  execute a request, the user submits a ThreadRequest derived command  
 *  object (functor) to the thread queue.  (I was going to call it threadJob but that's rude). 
 *  The request handler will pull this out of the queue, and run the functors operator() method. 
 *  If the queue is full, determined by the MAX_QUEUE_SIZE define, or the constructor parameter,  
 *  then the submitRequest method will block preventing new items being added to the queue.   
 *  These are implemented via a ManualEvent object. 
 * 
 *	@warning Exceptions WILL NOT propogate out of the accept handler.  You MUST catch  
 *           your exceptions in the ThreadRequest derived functor. 
 * 
 *	@author Peter Hancock 
 */ 
class ThreadPool 
{ 
public: 
	ThreadPool(int threadSize=THREAD_COUNT, int queueSize=MAX_QUEUE_SIZE); 
	virtual ~ThreadPool(); 
 
	int accept();														 ///< Start pool for acceptance 
	void submitRequest(ThreadRequest *request);							 ///< Submits a job to the pool for later attachment 
	void shutdown();													 ///< Shuts down the thread pool 
 
protected: 
	virtual void onThreadStart(int threadId) throw();					///< Runs on EACH thread initialization.   
	virtual void onThreadFinish(int threadId) throw();					///< Runs on EACH thread termination. 
 
private: 
	bool alive;														 ///< Contains the suicide pill to close down threads 
	std::vector pool;											///< thread handle pool 
	int threads;														///< Number of threads in the pool 
 
	static unsigned int __stdcall internalThreadProc(void* lpParam);	 ///< internal thread proc to run acceptance handlers 
	void acceptHandler(unsigned int threadId) throw();					 ///< Internal acceptance handler run the the internalThreadProc 
	void *threadData;											///< Pointer to thread data 
	std::queue jobQueue;						///< Pointer to request objects 
	Semaphore queueAccess;										///< Ensure that only queue number or max threads will access queue at once 
	CriticalSection queueGuard;									///< Ensure that the job Queue is threadsafe 
	ManualEvent notFull;										///< Event signalled when queue is not full 
 
	ThreadPool(const ThreadPool&);								// Disable copy and assignment 
	ThreadPool& operator=(const ThreadPool&); 
 
}; 
 
/** 
 *	Thrown when the thread pool is shutting down. 
 *	The submitRequest throws this once the threadPool has been requested to terminate.  Prevents clients 
 *	from adding requests to the thread pool queue that won't be handled. 
 * 
 *	@author Peter Hancock 
 */ 
class ThreadPoolShutdownException : public std::exception 
{ 
public: 
	ThreadPoolShutdownException(){} 
	ThreadPoolShutdownException(const char* mesg) : std::exception(mesg){} 
	~ThreadPoolShutdownException(){} 
};