Files
DBService/common/thread.cpp
T
2026-07-09 11:27:59 +08:00

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 );
}