#ifdef _WIN32 #include #include #else //!WIN32 #include #include #include #include #include #include #endif #include #include "typedef.h" #include "debug.h" #include "thread.h" CSema::CSema(const char *sName, unsigned int nInit, bool bCreate) { m_bCreate = bCreate; if (!m_bCreate) return; #ifdef _WIN32 m_hSema = CreateSemaphore(NULL,nInit,0xffff,NULL); if (!m_hSema){ #else semCount = nInit; if( pthread_mutex_init(&mutex, NULL) || pthread_cond_init(&condition, NULL) ){ #endif DebugPrint("Create semaphore error, errno=%d\n", errno ); } } CSema::~CSema() { if (!m_bCreate) return; int rc = 0; #ifdef _WIN32 if( !(rc=CloseHandle(m_hSema)) ){ #else rc = pthread_mutex_destroy(&mutex); if( rc ){ DebugPrint( "destroy mutex ret %d\n", rc ); } rc = pthread_cond_destroy(&condition); if( rc ){ #endif DebugPrint("delete semaphore error %d\n", rc ); } } int CSema::ActP(DWORD dwTimeout) { if (!m_bCreate) return -1; int ret; #ifdef _WIN32 ret = WaitForSingleObject(m_hSema, dwTimeout); if( ret==WAIT_TIMEOUT ){ #else if( dwTimeout==INFINITE ){ if( (ret=pthread_mutex_lock(&mutex))==0 ){ while( semCount<=0 ){ if( (ret=pthread_cond_wait(&condition, &mutex)) ){ break; } } if( !ret ) semCount--; pthread_mutex_unlock(&mutex); } else{ DebugPrint( "lock mutex error %d.\n", ret ); } } else{ if( (ret = pthread_mutex_lock(&mutex))==0 ){ timeval tv; // struct timezone tz; timespec tm; gettimeofday (&tv , /*&tz*/NULL); tm.tv_sec = tv.tv_sec + dwTimeout/1000 + ( tv.tv_usec + (dwTimeout%1000)*1000 ) / 1000000; tm.tv_nsec = 1000 * ( ( tv.tv_usec + (dwTimeout%1000)*1000 ) % 1000000 ); while( semCount<=0 ){ if( (ret=pthread_cond_timedwait( &condition, &mutex, &tm )) ){ break; } } if( !ret ) semCount--; pthread_mutex_unlock(&mutex); } else{ DebugPrint( "Lock mutext error %d.\n", ret ); } } if( ret==ETIMEDOUT ){ #endif // DebugPrint("WaitforSingleObject timeout!\n"); return 1; } else if( ret!=0 ){ DebugPrint( "sema wait error. errno=%d\n", errno ); } return ret; } void CSema::ActV() { if (!m_bCreate) return; #ifdef _WIN32 if (!ReleaseSemaphore(m_hSema,1,NULL)){ #else int rc; if( (rc = pthread_mutex_lock(&mutex)) ){ DebugPrint("mutex lock error.errno=%d\n", rc); return; } if( semCount<=0 ) semCount ++; pthread_mutex_unlock(&mutex); rc = pthread_cond_signal(&condition); if( rc ){ #endif DebugPrint("sema post error.errno=%d\n", errno); } } CMutexLock::CMutexLock(bool bCreate) { m_psmMut = new CSema( NULL, 1, bCreate ); m_psmMut->ActP(); } CMutexLock::CMutexLock(CSema * pSema, DWORD dwTimeOut) { m_psmMut = pSema; m_psmMut->ActP(dwTimeOut); } CMutexLock::~CMutexLock() { if( m_psmMut!=NULL ) m_psmMut->ActV(); } //////////////////////////////////////////////////////////////////// CThread::CThread(unsigned int stackSize, EPriority priorityLevel) #ifndef _WIN32 : m_smSuspend( NULL, 0 ), m_smSleep( NULL, 0 ) #endif { if(stackSize<=0){ DebugPrint("CThread 输入参数不正确\n"); } m_bSuspend = true; m_bExit = false; m_nStackSize = stackSize; // DebugPrint("create CThread with stacksize of %d\n", stackSize); #ifdef _WIN32 m_hThreadHandle = (HANDLE)_beginthreadex(NULL, stackSize, MainFunction, this, CREATE_SUSPENDED, &m_nThreadId); // m_bSuspend = true; #else pthread_attr_init(&m_tAttr); pthread_attr_setstacksize( &m_tAttr, stackSize ); //pthread_attr_setschedpolicy( &m_tAttr, SCHED_RR ); //SCHED_RR 或者 SCHED_FIFO,程序必须要在超级用户下运行,否则失败 m_hThreadHandle = 0; // SetPriority(e_LowestPriority); // DebugPrint( "Set thread attributes.\n" ); //pthread_create( &m_hThreadHandle, &m_tAttr, MainFunction, this ); // DebugPrint("CThread constructure finished.\n" ); #endif SetPriority(priorityLevel); } CThread::~CThread() { #ifdef _WIN32 if( m_hThreadHandle != NULL ){ DWORD dwExitCode = 0; if( GetExitCodeThread(m_hThreadHandle, &dwExitCode)==0){ DebugPrint("PThread::~PThread,GetExitCode failed errorcode=%d\n", GetLastError()); } else if( dwExitCode==STILL_ACTIVE ){ if (WAIT_OBJECT_0 != WaitForSingleObject(m_hThreadHandle,100)){ TerminateThread(m_hThreadHandle, 2); } } CloseHandle(m_hThreadHandle); } #else pthread_join( m_hThreadHandle, NULL ); pthread_attr_destroy( &m_tAttr ); #endif } void CThread::ExitThread() { #ifdef _WIN32 _endthreadex(0); #else pthread_exit(0); #endif } #ifdef _WIN32 unsigned int __stdcall CThread::MainFunction(void *threadPtr) #else void* CThread::MainFunction(void *threadPtr) #endif { if(threadPtr==NULL){ DebugPrint("CThread::MainFunction threadPtr is NULL!\n"); } else{ CThread *thread = (CThread *)threadPtr; // DebugPrint("Get CThread object 0x%X\n", (long)thread ); thread->Main(); } #ifdef _WIN32 return 0; #else return NULL; #endif } void CThread::Suspend() { if (m_bSuspend) return; // DebugPrint( "Suspend in.\n" ); m_bSuspend = true; #ifdef _WIN32 SuspendThread(m_hThreadHandle); #else m_smSuspend.ActP(); #endif // DebugPrint( "Suspend out.\n" ); } void CThread::Terminate() { if (m_bExit) return; m_bExit = true; } void CThread::Resume() { if (!m_bSuspend) return; m_bSuspend = false; // DebugPrint( "Resume call.\n" ); #ifdef _WIN32 ResumeThread(m_hThreadHandle); #else if( !m_hThreadHandle ){ int err = pthread_create( &m_hThreadHandle, &m_tAttr, MainFunction, this ); if(err!=0) DebugPrint( "create pthread return %d\n", err ); } else{ m_smSuspend.ActV(); } #endif } void CThread::SetPriority(EPriority priorityLevel) { #ifdef _WIN32 int nPrior; switch (priorityLevel){ case e_LowestPriority: nPrior = THREAD_PRIORITY_LOWEST; break; case e_LowPriority: nPrior = THREAD_PRIORITY_BELOW_NORMAL; break; case e_NormalPriority: nPrior = THREAD_PRIORITY_NORMAL; break; case e_HighPriority: nPrior = THREAD_PRIORITY_ABOVE_NORMAL; break; case e_HighestPriority: nPrior = THREAD_PRIORITY_TIME_CRITICAL; break; default: break; } if (!SetThreadPriority(m_hThreadHandle,nPrior)) { #else int policy; pthread_attr_getschedpolicy( &m_tAttr, &policy ); int max = sched_get_priority_max( policy ); int min = sched_get_priority_min( policy ); sched_param sp; pthread_attr_getschedparam( &m_tAttr, &sp ); sp.sched_priority = priorityLevel * (max-min) / (e_NumPriorities-1) + 1; if( -1==pthread_attr_setschedparam(&m_tAttr, &sp) ){ #endif DebugPrint("set priority failed.\n"); } } void CThread::Sleep(DWORD dwMilliseconds) { // DebugPrint( "Sleep %dms\n", dwMilliseconds ); #ifdef _WIN32 ::Sleep(dwMilliseconds); #else m_smSleep.ActP( dwMilliseconds ); #endif // DebugPrint( "Sleep %dms over\n", dwMilliseconds ); }