简单的线程池

来源:互联网 发布:java程序设计教程视频 编辑:程序博客网 时间:2024/06/10 06:29
#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;elseretval = 0;break;}}return retval;}void fire(bool all = false){if ( all )pthread_cond_broadcast(&_cond);elsepthread_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__

0 0
原创粉丝点击