SPprocthreadpool 线程池源码阅读

/*
 * Copyright 2007-2008 Stephen Liu
 * For license terms, see the file COPYING along with this library.
 */

#ifndef __spprocthread_hpp__
#define __spprocthread_hpp__

#include <pthread.h>

typedef struct tagSP_ProcThread SP_ProcThread_t;

class SP_ProcThreadPool {
public:
	typedef void ( * DispatchFunc_t )( void * );

	SP_ProcThreadPool( int maxThreads, const char * tag = 0 );
	~SP_ProcThreadPool();

	// set a callback for when all threads are idle
	void setFullCallback( DispatchFunc_t fullCallback, void * arg );

	/// @return 0 : OK, -1 : cannot create thread
	int dispatch( DispatchFunc_t dispatchFunc, void *arg );

	void wait4idler();

	int getMaxThreads();

private:
	char * mTag;

	int mMaxThreads;
	int mIndex;
	int mTotal;
	int mIsShutdown;

	pthread_mutex_t mMainMutex;
	pthread_cond_t mIdleCond;
	pthread_cond_t mFullCond;
	pthread_cond_t mEmptyCond;

	SP_ProcThread_t ** mThreadList;

	DispatchFunc_t mFullCallback;
	void * mFullCallbackArg;

	static void * wrapperFunc( void * );
	int saveThread( SP_ProcThread_t * thread );
};

#endif


 

 

/*
 * Copyright 2007-2008 Stephen Liu
 * For license terms, see the file COPYING along with this library.
 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <syslog.h>

#include "spprocthread.hpp"

typedef struct tagSP_ProcThread {
	pthread_t mId;
	pthread_mutex_t mMutex;
	pthread_cond_t mCond;
	SP_ProcThreadPool::DispatchFunc_t mFunc;
	void * mArg;
	SP_ProcThreadPool * mParent;
} SP_ProcThread_t;

SP_ProcThreadPool :: SP_ProcThreadPool( int maxThreads, const char * tag )
{
	if( maxThreads <= 0 ) maxThreads = 2;

	pthread_mutex_init( &mMainMutex, NULL );
	pthread_cond_init( &mIdleCond, NULL );
	pthread_cond_init( &mFullCond, NULL );
	pthread_cond_init( &mEmptyCond, NULL );
	mMaxThreads = maxThreads;
	mIndex = 0;
	mIsShutdown = 0;
	mTotal = 0;

	tag = NULL == tag ? "unknown" : tag;
	mTag = strdup( tag );

	mThreadList = ( SP_ProcThread_t ** )malloc( sizeof( void * ) * mMaxThreads );
	memset( mThreadList, 0, sizeof( void * ) * mMaxThreads );

	mFullCallback = NULL;
	mFullCallbackArg = NULL;
}

SP_ProcThreadPool :: ~SP_ProcThreadPool()
{
	pthread_mutex_lock( &mMainMutex );

	if( mIndex < mTotal ) {
		syslog( LOG_DEBUG, "[tp@%s] waiting for %d thread(s) to finish\n", mTag, mTotal - mIndex );
		pthread_cond_wait( &mFullCond, &mMainMutex );
	}

	mIsShutdown = 1;

	for( int i = 0; i < mIndex; i++ ) {
		SP_ProcThread_t * thread = mThreadList[ i ];
		pthread_mutex_lock( &thread->mMutex );
		pthread_cond_signal( &thread->mCond ) ;
		pthread_mutex_unlock ( &thread->mMutex );
	}

	if( mTotal > 0 ) {
		syslog( LOG_DEBUG, "[tp@%s] waiting for %d thread(s) to exit\n", mTag, mTotal );
		pthread_cond_wait( &mEmptyCond, &mMainMutex );
	}

	syslog( LOG_DEBUG, "[tp@%s] destroy %d thread structure(s)\n", mTag, mIndex );
	for( int i = 0; i < mIndex; i++ ) {
		SP_ProcThread_t * thread = mThreadList[ i ];
		pthread_mutex_destroy( &thread->mMutex );
		pthread_cond_destroy( &thread->mCond );
		free( thread );
		mThreadList[ i ] = NULL;
	}

	pthread_mutex_unlock( &mMainMutex );

	mIndex = 0;

	pthread_mutex_destroy( &mMainMutex );
	pthread_cond_destroy( &mIdleCond );
	pthread_cond_destroy( &mFullCond );
	pthread_cond_destroy( &mEmptyCond );

	free( mThreadList );
	mThreadList = NULL;

	free( mTag );
	mTag = NULL;
}

void SP_ProcThreadPool :: setFullCallback( DispatchFunc_t fullCallback, void * arg )
{
	mFullCallback = fullCallback;
	mFullCallbackArg = arg;
}

int SP_ProcThreadPool :: getMaxThreads()
{
	return mMaxThreads;
}

int SP_ProcThreadPool :: dispatch( DispatchFunc_t dispatchFunc, void *arg )
{
	int ret = 0;

	pthread_attr_t attr;
	SP_ProcThread_t * thread = NULL;

	pthread_mutex_lock( &mMainMutex );

	if( mIndex <= 0 && mTotal >= mMaxThreads ) {
		pthread_cond_wait( &mIdleCond, &mMainMutex );
	}

	if( mIndex <= 0 ) {
		SP_ProcThread_t * thread = ( SP_ProcThread_t * )malloc( sizeof( SP_ProcThread_t ) );
		thread->mId = 0;
		pthread_mutex_init( &thread->mMutex, NULL );
		pthread_cond_init( &thread->mCond, NULL );
		thread->mFunc = dispatchFunc;
		thread->mArg = arg;
		thread->mParent = this;

		pthread_attr_init( &attr );
		pthread_attr_setdetachstate( &attr,PTHREAD_CREATE_DETACHED );

		if( 0 == pthread_create( &( thread->mId ), &attr, wrapperFunc, thread ) ) {
			mTotal++;
			syslog( LOG_DEBUG, "[tp@%s] create thread#%ld\n", mTag, thread->mId );
		} else {
			ret = -1;
			syslog( LOG_WARNING, "[tp@%s] cannot create thread\n", mTag );
			pthread_mutex_destroy( &thread->mMutex );
			pthread_cond_destroy( &thread->mCond );
			free( thread );
		}
		pthread_attr_destroy( &attr );
	} else {
		mIndex--;
		thread = mThreadList[ mIndex ];
		mThreadList[ mIndex ] = NULL;

		thread->mFunc = dispatchFunc;
		thread->mArg = arg;
		thread->mParent = this;

		pthread_mutex_lock( &thread->mMutex );
		pthread_cond_signal( &thread->mCond ) ;//唤醒空闲线程继续工作
		pthread_mutex_unlock ( &thread->mMutex );
	}

	pthread_mutex_unlock( &mMainMutex );

	return ret;
}

void SP_ProcThreadPool :: wait4idler()
{
	if( mIndex <= 0 && mTotal >= mMaxThreads ) {
		pthread_mutex_lock( &mMainMutex );
		if( mIndex <= 0 && mTotal >= mMaxThreads ) {
			pthread_cond_wait( &mIdleCond, &mMainMutex );
		}
		pthread_mutex_unlock( &mMainMutex );
	}
}

void * SP_ProcThreadPool :: wrapperFunc( void * arg )
{
	SP_ProcThread_t * thread = ( SP_ProcThread_t * )arg;

	for( ; 0 == thread->mParent->mIsShutdown; ) {
		thread->mFunc( thread->mArg );

		pthread_mutex_lock( &thread->mMutex );
		if( 0 == thread->mParent->saveThread( thread ) ) {
			pthread_cond_wait( &thread->mCond, &thread->mMutex );//工作线程 完成此次工作,进入等待状态,等待主控进程的唤醒
			pthread_mutex_unlock( &thread->mMutex );
		} else {
			pthread_mutex_unlock( &thread->mMutex );
			pthread_cond_destroy( &thread->mCond );
			pthread_mutex_destroy( &thread->mMutex );

			free( thread );
			thread = NULL;
			break;
		}
	}

	if( NULL != thread ) {
		pthread_mutex_lock( &thread->mParent->mMainMutex );
		thread->mParent->mTotal--;
		if( thread->mParent->mTotal <= 0 ) {
			pthread_cond_signal( &thread->mParent->mEmptyCond );
		}
		pthread_mutex_unlock( &thread->mParent->mMainMutex );
	}

	return NULL;
}

int SP_ProcThreadPool :: saveThread( SP_ProcThread_t * thread )
{
	int ret = -1;

	pthread_mutex_lock( &mMainMutex );

	if( mIndex < mMaxThreads ) {
		mThreadList[ mIndex ] = thread;
		mIndex++;
		ret = 0;

		pthread_cond_signal( &mIdleCond );//通知Master线程 有线程已经空闲下来

		if( mIndex >= mTotal ) {
			if( NULL != mFullCallback ) mFullCallback( mFullCallbackArg );// 此时如果所有的线程都处于活动状态,则调用此函数。此函数进行扩充
			pthread_cond_signal( &mFullCond );// 告诉master线程已满
		}
	}

	pthread_mutex_unlock( &mMainMutex );

	return ret;
}


线程池是使用主线程来进行分发,各个工作线程是一个循环不停的工作,当完成一个函数的功能时发出空闲的信号,主线程进行记录。

 

可以使用两个队列来完成线程池的功能,一个是工作线程队列。一个是空闲线程队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值