int dispatch_threadpool(threadpool from_me, dispatch_fn dispatch_to_here, void *arg) { int ret = 0; _threadpool *pool = (_threadpool *) from_me; sp_thread_attr_t attr; _thread * thread = NULL; // add your code here to dispatch a thread sp_thread_mutex_lock( &pool->tp_mutex ); // printf("==========dispatch_threadpool\n"); while( pool->tp_index <= 0 && pool->tp_total >= pool->tp_max_index ) { //printf("all thread is busy!~~\n"); sp_thread_cond_wait( &pool->tp_idle, &pool->tp_mutex ); } if( pool->tp_index <= 0 ) { _thread * thread = ( _thread * )malloc( sizeof( _thread ) ); memset( &( thread->id ), 0, sizeof( thread->id ) ); sp_thread_mutex_init( &thread->mutex, NULL ); sp_thread_cond_init( &thread->cond, NULL ); thread->fn = dispatch_to_here; thread->arg = arg; thread->parent = pool; sp_thread_attr_init( &attr ); sp_thread_attr_setdetachstate( &attr, SP_THREAD_CREATE_DETACHED ); if( 0 == sp_thread_create( &thread->id, &attr, wrapper_fn, thread ) ) { pool->tp_total++; // printf( "create thread#%ld\n", thread->id ); } else { ret = -1; //printf( "cannot create thread\n" ); sp_thread_mutex_destroy( &thread->mutex ); sp_thread_cond_destroy( &thread->cond ); free( thread ); } } else { pool->tp_index--; thread = pool->tp_list[ pool->tp_index ]; pool->tp_list[ pool->tp_index ] = NULL; thread->fn = dispatch_to_here; thread->arg = arg; thread->parent = pool; sp_thread_mutex_lock( &thread->mutex ); sp_thread_cond_signal( &thread->cond ) ; sp_thread_mutex_unlock ( &thread->mutex ); } sp_thread_mutex_unlock( &pool->tp_mutex ); return ret; }
int SP_IocpLFServer :: run() { int ret = 0; int listenFD = -1; ret = SP_IOUtils::tcpListen( mBindIP, mPort, &listenFD, 0 ); if( 0 == ret ) { mCompletionHandler = mAcceptArg->mHandlerFactory->createCompletionHandler(); SP_IocpMsgQueue * msgQueue = new SP_IocpMsgQueue( mEventArg->getCompletionPort(), SP_IocpEventCallback::eKeyMsgQueue, SP_IocpEventCallback::onResponse, mEventArg ); mEventArg->setResponseQueue( msgQueue ); mEventArg->loadDisconnectEx( listenFD ); mAcceptArg->mAcceptEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); mAcceptArg->mListenSocket = (HANDLE)listenFD; if( NULL == CreateIoCompletionPort( mAcceptArg->mListenSocket, mEventArg->getCompletionPort(), SP_IocpEventCallback::eKeyAccept, 0 ) ) { sp_syslog( LOG_ERR, "CreateIoCompletionPort fail, errno %d", WSAGetLastError() ); return -1; } if( NULL == mAcceptArg->mIOChannelFactory ) { mAcceptArg->mIOChannelFactory = new SP_DefaultIOChannelFactory(); } sp_thread_t thread; ret = sp_thread_create( &thread, NULL, acceptThread, mAcceptArg ); if( 0 == ret ) { sp_syslog( LOG_NOTICE, "Thread #%ld has been created to accept socket", thread ); } else { sp_syslog( LOG_WARNING, "Unable to create a thread to accept socket, %s", strerror( errno ) ); return -1; } mIsRunning = 1; mThreadPool = new SP_ThreadPool( mMaxThreads ); for( int i = 0; i < mMaxThreads; i++ ) { mThreadPool->dispatch( lfHandler, this ); } } return ret; }
int SP_IocpServer :: run() { int ret = -1; sp_thread_attr_t attr; sp_thread_attr_init( &attr ); assert( sp_thread_attr_setstacksize( &attr, 1024 * 1024 ) == 0 ); sp_thread_attr_setdetachstate( &attr, SP_THREAD_CREATE_DETACHED ); sp_thread_t thread; ret = sp_thread_create( &thread, &attr, eventLoop, this ); sp_thread_attr_destroy( &attr ); if( 0 == ret ) { sp_syslog( LOG_NOTICE, "Thread #%ld has been created to listen on port [%d]", thread, mPort ); } else { mIsRunning = 0; sp_syslog( LOG_WARNING, "Unable to create a thread for TCP server on port [%d], %s", mPort, strerror( errno ) ) ; } return ret; }
int SP_IocpDispatcher :: dispatch() { int ret = -1; sp_thread_attr_t attr; sp_thread_attr_init( &attr ); assert( sp_thread_attr_setstacksize( &attr, 1024 * 1024 ) == 0 ); sp_thread_attr_setdetachstate( &attr, SP_THREAD_CREATE_DETACHED ); sp_thread_t thread; ret = sp_thread_create( &thread, &attr, eventLoop, this ); sp_thread_attr_destroy( &attr ); if( 0 == ret ) { sp_syslog( LOG_NOTICE, "Thread #%ld has been created for dispatcher", thread ); } else { mIsRunning = 0; sp_syslog( LOG_WARNING, "Unable to create a thread for dispatcher, %s", strerror( errno ) ) ; } return ret; }
int SP_IocpServer :: start() { #ifdef SIGPIPE /* Don't die with SIGPIPE on remote read shutdown. That's dumb. */ signal( SIGPIPE, SIG_IGN ); #endif int ret = 0; int listenFD = -1; ret = SP_IOUtils::tcpListen( mBindIP, mPort, &listenFD, 0 ); if( 0 == ret ) { SP_IocpEventArg eventArg( mTimeout ); eventArg.loadDisconnectEx( listenFD ); SP_IocpMsgQueue * msgQueue = new SP_IocpMsgQueue( eventArg.getCompletionPort(), SP_IocpEventCallback::eKeyMsgQueue, SP_IocpEventCallback::onResponse, &eventArg ); eventArg.setResponseQueue( msgQueue ); mCompletionPort = eventArg.getCompletionPort(); if( NULL == mIOChannelFactory ) { mIOChannelFactory = new SP_DefaultIOChannelFactory(); } SP_IocpAcceptArg_t acceptArg; memset( &acceptArg, 0, sizeof( acceptArg ) ); acceptArg.mHandlerFactory = mHandlerFactory; acceptArg.mIOChannelFactory = mIOChannelFactory; acceptArg.mReqQueueSize = mReqQueueSize; acceptArg.mMaxConnections = mMaxConnections; acceptArg.mRefusedMsg = mRefusedMsg; acceptArg.mAcceptEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); acceptArg.mEventArg = &eventArg; acceptArg.mListenSocket = (HANDLE)listenFD; if( NULL == CreateIoCompletionPort( acceptArg.mListenSocket, eventArg.getCompletionPort(), SP_IocpEventCallback::eKeyAccept, 0 ) ) { sp_syslog( LOG_ERR, "CreateIoCompletionPort fail, errno %d", WSAGetLastError() ); return -1; } sp_thread_t thread; ret = sp_thread_create( &thread, NULL, acceptThread, &acceptArg ); if( 0 == ret ) { sp_syslog( LOG_NOTICE, "Thread #%ld has been created to accept socket", thread ); } else { sp_syslog( LOG_WARNING, "Unable to create a thread to accept socket, %s", strerror( errno ) ); return -1; } SP_Executor actExecutor( 1, "act" ); SP_Executor workerExecutor( mMaxThreads, "work" ); SP_CompletionHandler * completionHandler = mHandlerFactory->createCompletionHandler(); /* Start the event loop. */ while( 0 == mIsShutdown ) { SP_IocpEventCallback::eventLoop( &eventArg, &acceptArg ); for( ; NULL != eventArg.getInputResultQueue()->top(); ) { SP_Task * task = (SP_Task*)eventArg.getInputResultQueue()->pop(); workerExecutor.execute( task ); } for( ; NULL != eventArg.getOutputResultQueue()->top(); ) { SP_Message * msg = (SP_Message*)eventArg.getOutputResultQueue()->pop(); void ** arg = ( void** )malloc( sizeof( void * ) * 2 ); arg[ 0 ] = (void*)completionHandler; arg[ 1 ] = (void*)msg; actExecutor.execute( outputCompleted, arg ); } } delete completionHandler; sp_syslog( LOG_NOTICE, "Server is shutdown." ); sp_close( listenFD ); } return ret; }