提交 7859f2469eb4b00b43a8e25b2c2805f157371ab8

作者 LJH 李佳桓
1 个父辈 11c30e7c

add

正在显示 1 个修改的文件 包含 211 行增加0 行删除
  1 +/*
  2 + * Copyright 2007 Stephen Liu
  3 + * For license terms, see the file COPYING along with this library.
  4 + */
  5 +
  6 +#include <stdlib.h>
  7 +#include <string.h>
  8 +#include <stdio.h>
  9 +
  10 +#include "spporting.hpp"
  11 +
  12 +#include "spthreadpool.hpp"
  13 +
  14 +typedef struct tagSP_Thread {
  15 + sp_thread_t mId;
  16 + sp_thread_mutex_t mMutex;
  17 + sp_thread_cond_t mCond;
  18 + SP_ThreadPool::DispatchFunc_t mFunc;
  19 + void * mArg;
  20 + SP_ThreadPool * mParent;
  21 +} SP_Thread_t;
  22 +
  23 +SP_ThreadPool :: SP_ThreadPool( int maxThreads, const char * tag )
  24 +{
  25 + if( maxThreads <= 0 ) maxThreads = 2;
  26 +
  27 + sp_thread_mutex_init( &mMainMutex, NULL );
  28 + sp_thread_cond_init( &mIdleCond, NULL );
  29 + sp_thread_cond_init( &mFullCond, NULL );
  30 + sp_thread_cond_init( &mEmptyCond, NULL );
  31 + mMaxThreads = maxThreads;
  32 + mIndex = 0;
  33 + mIsShutdown = 0;
  34 + mTotal = 0;
  35 +
  36 + tag = NULL == tag ? "unknown" : tag;
  37 + mTag = strdup( tag );
  38 +
  39 + mThreadList = ( SP_Thread_t ** )malloc( sizeof( void * ) * mMaxThreads );
  40 + memset( mThreadList, 0, sizeof( void * ) * mMaxThreads );
  41 +}
  42 +
  43 +SP_ThreadPool :: ~SP_ThreadPool()
  44 +{
  45 + sp_thread_mutex_lock( &mMainMutex );
  46 +
  47 + if( mIndex < mTotal ) {
  48 + sp_syslog( LOG_NOTICE, "[tp@%s] waiting for %d thread(s) to finish\n", mTag, mTotal - mIndex );
  49 + sp_thread_cond_wait( &mFullCond, &mMainMutex );
  50 + }
  51 +
  52 + mIsShutdown = 1;
  53 +
  54 + int i = 0;
  55 +
  56 + for( i = 0; i < mIndex; i++ ) {
  57 + SP_Thread_t * thread = mThreadList[ i ];
  58 + sp_thread_mutex_lock( &thread->mMutex );
  59 + sp_thread_cond_signal( &thread->mCond ) ;
  60 + sp_thread_mutex_unlock ( &thread->mMutex );
  61 + }
  62 +
  63 + if( mTotal > 0 ) {
  64 + sp_syslog( LOG_NOTICE, "[tp@%s] waiting for %d thread(s) to exit\n", mTag, mTotal );
  65 + sp_thread_cond_wait( &mEmptyCond, &mMainMutex );
  66 + }
  67 +
  68 + sp_syslog( LOG_NOTICE, "[tp@%s] destroy %d thread structure(s)\n", mTag, mIndex );
  69 + for( i = 0; i < mIndex; i++ ) {
  70 + SP_Thread_t * thread = mThreadList[ i ];
  71 + sp_thread_mutex_destroy( &thread->mMutex );
  72 + sp_thread_cond_destroy( &thread->mCond );
  73 + free( thread );
  74 + mThreadList[ i ] = NULL;
  75 + }
  76 +
  77 + sp_thread_mutex_unlock( &mMainMutex );
  78 +
  79 + mIndex = 0;
  80 +
  81 + sp_thread_mutex_destroy( &mMainMutex );
  82 + sp_thread_cond_destroy( &mIdleCond );
  83 + sp_thread_cond_destroy( &mFullCond );
  84 + sp_thread_cond_destroy( &mEmptyCond );
  85 +
  86 + free( mThreadList );
  87 + mThreadList = NULL;
  88 +
  89 + free( mTag );
  90 + mTag = NULL;
  91 +}
  92 +
  93 +int SP_ThreadPool :: getMaxThreads()
  94 +{
  95 + return mMaxThreads;
  96 +}
  97 +
  98 +int SP_ThreadPool :: dispatch( DispatchFunc_t dispatchFunc, void *arg )
  99 +{
  100 + int ret = 0;
  101 +
  102 + sp_thread_attr_t attr;
  103 + SP_Thread_t * thread = NULL;
  104 +
  105 + sp_thread_mutex_lock( &mMainMutex );
  106 +
  107 + for( ; mIndex <= 0 && mTotal >= mMaxThreads; ) {
  108 + sp_thread_cond_wait( &mIdleCond, &mMainMutex );
  109 + }
  110 +
  111 + if( mIndex <= 0 ) {
  112 + SP_Thread_t * thread = ( SP_Thread_t * )malloc( sizeof( SP_Thread_t ) );
  113 + memset( &thread->mId, 0, sizeof( thread->mId ) );
  114 + sp_thread_mutex_init( &thread->mMutex, NULL );
  115 + sp_thread_cond_init( &thread->mCond, NULL );
  116 + thread->mFunc = dispatchFunc;
  117 + thread->mArg = arg;
  118 + thread->mParent = this;
  119 +
  120 + sp_thread_attr_init( &attr );
  121 + sp_thread_attr_setdetachstate( &attr, SP_THREAD_CREATE_DETACHED );
  122 +
  123 + if( 0 == sp_thread_create( &( thread->mId ), &attr, wrapperFunc, thread ) ) {
  124 + mTotal++;
  125 + sp_syslog( LOG_NOTICE, "[tp@%s] create thread#%ld\n", mTag, thread->mId );
  126 + } else {
  127 + ret = -1;
  128 + sp_syslog( LOG_WARNING, "[tp@%s] cannot create thread\n", mTag );
  129 + sp_thread_mutex_destroy( &thread->mMutex );
  130 + sp_thread_cond_destroy( &thread->mCond );
  131 + free( thread );
  132 + }
  133 + sp_thread_attr_destroy( &attr );
  134 + } else {
  135 + mIndex--;
  136 + thread = mThreadList[ mIndex ];
  137 + mThreadList[ mIndex ] = NULL;
  138 +
  139 + thread->mFunc = dispatchFunc;
  140 + thread->mArg = arg;
  141 + thread->mParent = this;
  142 +
  143 + sp_thread_mutex_lock( &thread->mMutex );
  144 + sp_thread_cond_signal( &thread->mCond ) ;
  145 + sp_thread_mutex_unlock ( &thread->mMutex );
  146 + }
  147 +
  148 + sp_thread_mutex_unlock( &mMainMutex );
  149 +
  150 + return ret;
  151 +}
  152 +
  153 +sp_thread_result_t SP_THREAD_CALL SP_ThreadPool :: wrapperFunc( void * arg )
  154 +{
  155 + SP_Thread_t * thread = ( SP_Thread_t * )arg;
  156 +
  157 + for( ; 0 == thread->mParent->mIsShutdown; ) {
  158 + thread->mFunc( thread->mArg );
  159 +
  160 + if( 0 != thread->mParent->mIsShutdown ) break;
  161 +
  162 + sp_thread_mutex_lock( &thread->mMutex );
  163 + if( 0 == thread->mParent->saveThread( thread ) ) {
  164 + sp_thread_cond_wait( &thread->mCond, &thread->mMutex );
  165 + sp_thread_mutex_unlock( &thread->mMutex );
  166 + } else {
  167 + sp_thread_mutex_unlock( &thread->mMutex );
  168 + sp_thread_cond_destroy( &thread->mCond );
  169 + sp_thread_mutex_destroy( &thread->mMutex );
  170 +
  171 + free( thread );
  172 + thread = NULL;
  173 + break;
  174 + }
  175 + }
  176 +
  177 + if( NULL != thread ) {
  178 + sp_thread_mutex_lock( &thread->mParent->mMainMutex );
  179 + thread->mParent->mTotal--;
  180 + if( thread->mParent->mTotal <= 0 ) {
  181 + sp_thread_cond_signal( &thread->mParent->mEmptyCond );
  182 + }
  183 + sp_thread_mutex_unlock( &thread->mParent->mMainMutex );
  184 + }
  185 +
  186 + return 0;
  187 +}
  188 +
  189 +int SP_ThreadPool :: saveThread( SP_Thread_t * thread )
  190 +{
  191 + int ret = -1;
  192 +
  193 + sp_thread_mutex_lock( &mMainMutex );
  194 +
  195 + if( mIndex < mMaxThreads ) {
  196 + mThreadList[ mIndex ] = thread;
  197 + mIndex++;
  198 + ret = 0;
  199 +
  200 + sp_thread_cond_signal( &mIdleCond );
  201 +
  202 + if( mIndex >= mTotal ) {
  203 + sp_thread_cond_signal( &mFullCond );
  204 + }
  205 + }
  206 +
  207 + sp_thread_mutex_unlock( &mMainMutex );
  208 +
  209 + return ret;
  210 +}
  211 +
... ...
注册登录 后发表评论