spserver学习之一__线程池调度模型

来源:互联网 发布:秀智为什么那么红 知乎 编辑:程序博客网 时间:2024/06/05 15:45

    从SP_Executor :: eventLoop开始,只要队列中有节点,则进入 ThreadPool的调度。


    (1) 当没有空闲线程且线程数量饱和时,进入等待,知道条件变量满足。

    (2)如果没有空闲线程,则创建线程 ,具体见wrapperFunc

    (3)如果有空闲线程,则分配该线程,设置其具体函数和参数,唤醒等待的线程,执行。     

    (4)唤醒等待的线程,使之执行。

    (5)每个线程执行具体的业务逻辑,如果该函数不能即使返回,该线程在外面看来,就是一个非空闲状态,dispatch时,如果(1)满足,则会创建新的线程。

    (6)(7)业务逻辑执行返回后,该线程及为空闲状态,执行saveThread,   就是将线程放入threadList;mIndex++,表示有空闲线程。这里留意下(6)的操作完后,使自己阻塞,(4)则唤醒,继续执行。

    (8) 使(1)出的条件变量满足,如果阻塞,则可往下走,进行调度


    sp_thread_mutex_lock( &mMainMutex );

    for( ; mIndex <= 0 && mTotal >= mMaxThreads; ) {                             -----------------------------------(1)
        i = sp_thread_cond_wait( &mIdleCond, &mMainMutex );
    }

    if( mIndex <= 0 ) {                                                                                                                       
        SP_Thread_t * thread = ( SP_Thread_t * )malloc( sizeof( SP_Thread_t ) );
        memset( &thread->mId, 0, sizeof( thread->mId ) );
        sp_thread_mutex_init( &thread->mMutex, NULL );
        sp_thread_cond_init( &thread->mCond, NULL );
        thread->mFunc = dispatchFunc;
        thread->mArg = arg;
        thread->mParent = this;

        sp_thread_attr_init( &attr );
        sp_thread_attr_setdetachstate( &attr, SP_THREAD_CREATE_DETACHED );

        if( 0 == sp_thread_create( &( thread->mId ), &attr, wrapperFunc, thread ) ) {                      -------------(2)
            mTotal++;  //mIndex++ in wrapperFunc
            sp_syslog( LOG_NOTICE, "[tp@%s] create thread#%ld\n", mTag, thread->mId );
        } else {
            ret = -1;
            sp_syslog( LOG_WARNING, "[tp@%s] cannot create thread\n", mTag );
            sp_thread_mutex_destroy( &thread->mMutex );
            sp_thread_cond_destroy( &thread->mCond );
            free( thread );
        }
        sp_thread_attr_destroy( &attr );
    } else {
        mIndex--;                                                                                                                                             ---------------(3)
        thread = mThreadList[ mIndex ];
        mThreadList[ mIndex ] = NULL;

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

        sp_thread_mutex_lock( &thread->mMutex );
        sp_thread_cond_signal( &thread->mCond ) ;                                                                               ------------------(4)
        sp_thread_mutex_unlock ( &thread->mMutex );
    }

    sp_thread_mutex_unlock( &mMainMutex );


sp_thread_result_t SP_THREAD_CALL SP_ThreadPool :: wrapperFunc( void * arg )
{
    SP_Thread_t * thread = ( SP_Thread_t * )arg;

    for( ; 0 == thread->mParent->mIsShutdown; ) {
        thread->mFunc( thread->mArg );  //business logic                                               ---------------------(5)

        if( 0 != thread->mParent->mIsShutdown ) break;

        sp_thread_mutex_lock( &thread->mMutex );
        if( 0 == thread->mParent->saveThread( thread ) ) {                                              -----------------------(6)
            sp_thread_cond_wait( &thread->mCond, &thread->mMutex );
            sp_thread_mutex_unlock( &thread->mMutex );
        } else {
            sp_thread_mutex_unlock( &thread->mMutex );
            sp_thread_cond_destroy( &thread->mCond );
            sp_thread_mutex_destroy( &thread->mMutex );

            free( thread );
            thread = NULL;
            break;
        }
    }
    .........
    return 0;
}


int SP_ThreadPool :: saveThread( SP_Thread_t * thread )
{
    int ret = -1;

    sp_thread_mutex_lock( &mMainMutex );

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

        sp_thread_cond_signal( &mIdleCond );                                                                    -------------------(8)

        if( mIndex >= mTotal ) {
            sp_thread_cond_signal( &mFullCond );
        }
    }

    sp_thread_mutex_unlock( &mMainMutex );

    return ret;
}


原创粉丝点击