简单的线程池

#ifndef __HLP_THREAD_POOL_H__
#define __HLP_THREAD_POOL_H__

#include <assert.h>
#include <list>
#include <pthread.h>
#include "winnix.h"
#include <iostream>

namespace hlp
{
	class mlock
	{
		pthread_mutex_t mtx;
	public:
		mlock()
		{
			pthread_mutex_init(&mtx, NULL);
		}

		~mlock()
		{
			pthread_mutex_destroy(&mtx);
		}

		int lock()
		{
			return pthread_mutex_lock(&mtx);
		}

		void unlock()
		{
			pthread_mutex_unlock(&mtx);
		}

		operator pthread_mutex_t*()
		{
			return &mtx;
		}
	};

	typedef bool (*pfncheck)(void* arg1, void* arg2);
	class mlockex
	{
	public:
		mlockex()
		{
			pthread_cond_init(&_cond, NULL);
		}

		~mlockex()
		{
			pthread_cond_destroy(&_cond);
		}

		void lock()
		{
			_lock.lock();
		}

		void unlock()
		{
			_lock.unlock();
		}

		int lock_wait(pfncheck fn, void* arg1, void* arg2, unsigned int mstmo = -1)
		{
			int retval = -1;
			_lock.lock();
			while ( fn( arg1, arg2 ) )
			{
				if ( mstmo == -1 )
				{
					pthread_cond_wait(&_cond, _lock);
					retval = 0;
				}
				else
				{
					struct timespec abstime;
					abstime.tv_sec = time(NULL) + mstmo/1000;
					abstime.tv_nsec = (mstmo%1000)*1000000;
					if ( ETIMEDOUT == pthread_cond_timedwait(&_cond, _lock, &abstime) )
						retval = 1;
					else
						retval = 0;
					break;
				}
			}
			return retval;
		}

		void fire(bool all = false)
		{
			if ( all )
				pthread_cond_broadcast(&_cond);
			else
				pthread_cond_signal(&_cond);
		}

	private:
		mlock _lock;
		pthread_cond_t _cond;
	};

	typedef void* (*pfntaskcb)(void* arg1, void* arg2);
	class mthreadpool
	{
	public:

		typedef enum _em_mthp_error_code
		{
			failed = -1,
			ok = 0
		}mthp_error_code;

		static mthreadpool* create(unsigned int max, unsigned int min = 0, unsigned int inc = 1, unsigned int max_lock_time = -1, unsigned int max_idle_time = -1)
		{
			mthreadpool* mthp = new mthreadpool();
			mthp->initialize(max, min, inc, max_lock_time, max_idle_time);
			return mthp;
		}

		static void mthreadpool::destroy(mthreadpool* mthp)
		{
			mthp->stop();
		}

	private:
		mthreadpool()
		{
		}

		~mthreadpool()
		{
		}

		class mtask_context
		{
		public:
			mtask_context()
			{
				cb = NULL;
				arg1 = arg2 = NULL;
			}

			void run()
			{
				if ( cb != NULL )
					cb( arg1, arg2 );
			}

			pfntaskcb cb;
			void* arg1;
			void* arg2;
		};

		class mthread_context
		{
		public:
			typedef enum _em_state_code{
				idle,
				busy
			}state_code;

			static bool none_task_callback_is_set(void* arg1, void* arg2)
			{
				pfntaskcb* cb = (pfntaskcb*)arg1;
				bool* pstopped = (bool*)arg2;
				return ((cb == NULL || *cb == NULL) && !(*pstopped));
			}
			static bool isbusy(void* arg1, void* arg2)
			{
				state_code* code = (state_code*)arg1;
				return (*code == state_code::busy);
			}
		public:
			mthread_context()
			{
				stopped = false;
				mtask = new mtask_context();
				update();
			}

			~mthread_context()
			{
				delete mtask;
			}

			bool is_busy()
			{
				bool isbusy = false;
				_state_lock.lock();
				isbusy = (state == state_code::busy);
				_state_lock.unlock();
				return isbusy;
			}

			int wait(unsigned int mstmo = -1)
			{
				int retval = _state_lock.lock_wait(isbusy, &state, NULL, mstmo);
				_state_lock.unlock();
				return retval;
			}

			void set_task(pfntaskcb cb, void* arg1, void* arg2, state_code _state)
			{
				mtask->cb = cb;
				mtask->arg1 = arg1;
				mtask->arg2 = arg2;
				_state_lock.lock();
				state = _state;
				_state_lock.unlock();
			}

			void set(pfntaskcb cb, void* arg1, void* arg2, state_code _state)
			{
				_task_lock.lock();
				set_task(cb, arg1, arg2, _state);
				_task_lock.unlock();
				dowork();
			}

			void dowork()
			{
				_task_lock.fire();
			}

			void done()
			{
				_state_lock.fire();
			}

			void set(mtask_context* t)
			{
				set(t->cb, t->arg1, t->arg2, state_code::busy);
			}

			mtask_context wait_for_task()
			{
				mtask_context mctx;
				_task_lock.lock_wait(none_task_callback_is_set, &mtask->cb, &stopped);
				mctx = *mtask;
				_task_lock.unlock();
				return mctx;
			}

			void update()
			{
				set(NULL, NULL, NULL, state_code::idle);
				lastupdate = time(NULL);
			}

			void run()
			{
				mtask_context _task = wait_for_task();
				_task.run();
				done();
				update();
			}


		public:
			pthread_t tid;
			mlockex _task_lock;
			mlockex _state_lock;
			mthreadpool* mpool;
			time_t lastupdate;
			state_code state;
			bool stopped;

			mtask_context* mtask;
		};

		static void* monitor_thread_proc(void* args)
		{
			pthread_detach(pthread_self());
			mthreadpool* pthis = (mthreadpool*)args;
	
			pthis->maintain_work_threads();

			return NULL;
		}

		static void* dispatch_thread_proc(void* args)
		{
			pthread_detach(pthread_self());

			mthreadpool* pthis = (mthreadpool*)args;
			pthis->dispatch();

			return NULL;
		}

		static void* mtask_thread_proc(void* args)
		{
			pthread_detach(pthread_self());

			mthread_context* mthc = (mthread_context*)args;
			while( !mthc->stopped )
			{
				mthc->run();
			}

			try
			{
				delete mthc;
			}
			catch(...)
			{}

			return NULL;
		}

		static bool none_task_to_do(void* arg1, void* arg2)
		{
			std::list<mtask_context*>* lmts = (std::list<mtask_context*>*)arg1;
			return (*lmts).empty();
		}

		unsigned int initialize(unsigned int max, unsigned int min, unsigned int inc, unsigned int max_lock_time, unsigned int max_idle_time)
		{
			_used_thread_count = 0;
			_stop = false;
			init_work_threads(max, min, inc, max_lock_time, max_idle_time);

			return mthp_error_code::ok;
		}

		unsigned int init_monitor_thread()
		{
			unsigned int retval = pthread_create(&_monitor_tid, 0, monitor_thread_proc, this);
			if ( retval < 0 )
				return mthp_error_code::failed;
			return mthp_error_code::ok;
		}

		unsigned int init_dispatch_thread()
		{
			unsigned int retval = pthread_create(&_dispatch_tid, 0, dispatch_thread_proc, this);
			if ( retval < 0 )
				return mthp_error_code::failed;
			return mthp_error_code::ok;
		}

		unsigned int init_work_threads(unsigned int max, unsigned int min, unsigned int inc, unsigned int max_lock_time, unsigned int max_idle_time)
		{
			if ( init_monitor_thread() != 0 || init_dispatch_thread() != 0 )
				return mthp_error_code::failed;

			auto_create_threads(min);
			_max_thread_count = max;
			_inc_thread_count = inc;
			_max_lock_time = max_lock_time;
			_max_idle_time = max_idle_time;

			return mthp_error_code::ok;
		}

		unsigned int auto_create_threads(unsigned int count)
		{
			unsigned int retval = 0;
			for ( unsigned int i = 0; i < count; i++ )
			{
				if ( 0 == create_thread_with_context() )
					retval++;
			}
			return retval;
		}

		unsigned int create_thread_with_context()
		{
			unsigned int code = mthp_error_code::failed;

			mthread_context* mthc = new mthread_context();
			do
			{
				mthc->mpool = this;
				unsigned int retval = pthread_create(&mthc->tid, 0, mtask_thread_proc, mthc);
				if ( retval != 0 )
					break;

				_thread_contexts_lock.lock();
				unsigned int count = _thread_contexts.size();
				if ( count < _max_thread_count )
				{
					_thread_contexts.push_back(mthc);
					code = mthp_error_code::ok;
				}
				_thread_contexts_lock.unlock();

			} while (0);

			if ( code != mthp_error_code::ok )
			{
				destroy_thread_with_context(mthc);
			}

			return code;
		}

		unsigned int destroy_thread_with_context(mthread_context* context)
		{
			context->stopped = true;
			pthread_cancel(context->tid);

			return mthp_error_code::ok;
		}

		unsigned int maintain_work_threads()
		{
			while( !_stop )
			{
				msleep(1000);

				time_t now = time(NULL);
				_thread_contexts_lock.lock();
				std::list<mthread_context*>::iterator iter = _thread_contexts.begin();
				for ( ; iter != _thread_contexts.end(); )
				{
					unsigned int lock_time = (unsigned int)(now - (*iter)->lastupdate);
					if ( (_max_lock_time != -1 && lock_time > _max_lock_time && (*iter)->is_busy())
						|| (_max_idle_time != -1 && lock_time > _max_idle_time) )
					{
						destroy_thread_with_context(*iter);
						iter = _thread_contexts.erase(iter);
					}
					else
					{
						++iter;
					}
				}
				_thread_contexts_lock.unlock();
			}

			return mthp_error_code::ok;
		}

		mthread_context* get()
		{
			mthread_context* mthc = NULL;

			_thread_contexts_lock.lock();
			std::list<mthread_context*>::iterator iter = _thread_contexts.begin();
			for ( ; iter != _thread_contexts.end(); ++iter )
			{
				if ( !(*iter)->is_busy() )
				{
					mthc = *iter;
					_thread_contexts.erase(iter);
					break;
				}
			}
			
			unsigned int allcnt = _thread_contexts.size()+_used_thread_count;
			if ( mthc == NULL && allcnt < _max_thread_count )
			{
				unsigned int retval = 0;
				for ( unsigned int i = 0; i < _inc_thread_count && (i+allcnt) < _max_thread_count; i++ )
				{
					mthread_context* mctx = new mthread_context();
					mctx->mpool = this;
					if ( 0 != pthread_create(&mctx->tid, 0, mtask_thread_proc, mctx) )
					{
						delete mctx;
						continue;
					}

					if ( i == 0 )
					{
						mthc = mctx;
						continue;
					}
					_thread_contexts.push_back(mctx);
				}
			}

			if ( mthc != NULL )
				++_used_thread_count;

			_thread_contexts_lock.unlock();

			return mthc;
		}

		void release(mthread_context* mthc)
		{
			if ( mthc == NULL )
				return;
			
			_thread_contexts_lock.lock();
			_thread_contexts.push_back(mthc);
			--_used_thread_count;
			_thread_contexts_lock.unlock();
		}

		void dispatch()
		{
			while(true)
			{
				_tasks_lock.lock_wait(none_task_to_do, &_tasks, NULL);

				mtask_context* t = _tasks.front();
				_tasks.pop_front();

				_tasks_lock.unlock();

				mthread_context* mthc = get();
				if ( mthc != NULL )
				{
					mthc->set(t);
					release(mthc);
				}
			
				delete t;
			}
		}

		void stop()
		{
			_stop = true;
			_thread_contexts_lock.lock();
			std::list<mthread_context*>::iterator iter = _thread_contexts.begin();
			for ( ; iter != _thread_contexts.end(); ++iter)
			{
				destroy_thread_with_context(*iter);
			}
			_thread_contexts_lock.unlock();

			pthread_join(_monitor_tid, NULL);
			pthread_join(_dispatch_tid, NULL);
		}

	public:
		unsigned int exec(pfntaskcb cb, void* arg1, void* arg2)
		{
			mtask_context* task = new mtask_context;
			task->cb = cb;
			task->arg1 = arg1;
			task->arg2 = arg2;

			_tasks_lock.lock();
			_tasks.push_back(task);
			_tasks_lock.unlock();
			_tasks_lock.fire();
		
			return mthp_error_code::ok;
		}

		unsigned int synexec(pfntaskcb cb, void* arg1, void* arg2, unsigned int tmo)
		{
			unsigned int retval = mthp_error_code::failed;
			mthread_context* mthc = get();
			if ( mthc != NULL )
			{
				mthc->set(cb, arg1, arg2, mthread_context::busy);
				if ( 0 == mthc->wait(tmo) )
					retval = mthp_error_code::ok;
				release(mthc);
			}

			return retval;
		}

	private:
		unsigned int _max_thread_count;
		unsigned int _inc_thread_count;

		unsigned int _max_lock_time;
		unsigned int _max_idle_time;

		unsigned int _used_thread_count;

		pthread_t _monitor_tid;
		pthread_t _dispatch_tid;

		std::list<mthread_context*> _thread_contexts;
		mlock _thread_contexts_lock;

		std::list<mtask_context*> _tasks;
		mlockex _tasks_lock;

		bool _stop;
	};

}

#endif // __HLP_THREAD_POOL_H__

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值