349 lines
7.5 KiB
C++
349 lines
7.5 KiB
C++
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#include <process.h>
|
|
#else //!WIN32
|
|
#include <pthread.h>
|
|
#include <sys/time.h>
|
|
#include <semaphore.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#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 );
|
|
}
|