📄 unixthreads.cpp
字号:
}
return retVal;
}
HX_RESULT HXUnixThread::DispatchMessage(HXThreadMessage* pMsg)
{
HX_ASSERT( "HXUnixThread::DispatchMessage is not implemented yet." == NULL );
return HXR_FAIL;
}
//=======================================================================
//
// HXUnixMutex
// ------------------
//
//=======================================================================
HXUnixMutex::HXUnixMutex()
{
}
HXUnixMutex::~HXUnixMutex()
{
}
HX_RESULT HXUnixMutex::MakeMutex( HXMutex*& pMutex )
{
#if defined( _LINUX ) || defined(_HPUX) || defined(_MAC_UNIX)
pMutex = new HXPthreadMutex();
#elif defined( _SOLARIS )
pMutex = new HXSolarisMutex();
#else
HX_ASSERT( "No unix mutex for this platform" == NULL );
#endif
if(pMutex == NULL)
{
HX_ASSERT( 0 );
return HXR_OUTOFMEMORY;
}
return HXR_OK;
}
HX_RESULT HXUnixMutex::Lock()
{
return _Lock();
}
HX_RESULT HXUnixMutex::Unlock()
{
return _Unlock();
}
HX_RESULT HXUnixMutex::Trylock()
{
return _TryLock();
}
//=======================================================================
//
// HXUnixSemaphore
// ------------------
//
//=======================================================================
HXUnixSemaphore::HXUnixSemaphore(UINT32 unInitialCount)
: m_unInitialCount(unInitialCount)
{
}
HXUnixSemaphore::~HXUnixSemaphore()
{
}
HX_RESULT HXUnixSemaphore::MakeSemaphore(HXUnixSemaphore*& pSem)
{
#if defined( _LINUX ) || defined(_HPUX)
pSem = new HXPthreadSemaphore();
#elif defined(_MAC_UNIX)
pSem = new HXPthreadMacSemaphore();
#elif defined( _SOLARIS )
pSem = new HXSolarisSemaphore();
#else
HX_ASSERT( "No unix semaphore for this platform" == NULL );
#endif
if(pSem == NULL)
{
HX_ASSERT(0);
return HXR_OUTOFMEMORY;
}
return HXR_OK;
}
HX_RESULT HXUnixSemaphore::Post()
{
return _Post();
}
HX_RESULT HXUnixSemaphore::Wait()
{
return _Wait();
}
HX_RESULT HXUnixSemaphore::TryWait()
{
return _TryWait();
}
HX_RESULT HXUnixSemaphore::GetValue( int* pnCount)
{
return _GetValue( pnCount );
}
//=======================================================================
//
// HXUnixEvent
// ------------------
//
//=======================================================================
HXUnixEvent::HXUnixEvent(const char* pEventName, BOOL bManualReset)
: m_bIsManualReset( bManualReset ),
m_bEventIsSet(FALSE),
m_pCondLock(NULL),
m_pCond(NULL)
{
//
// NOTE: Because of the way the windows Cond vars work we have:
//
// bManualReset==1 Once we signal once, all other signal/wait
// calls are noops. All threads awake.
// bManualReset==0 Once signaled we retain until someone Waits.
// Once someone waits, only one thread wakes up
// and the signal is reset.
//
//Create the condition with its associated mutex.
//Do NOT delete the mutex that the cond makes for us....
HXUnixCondition::MakeCondition(m_pCond, m_pCondLock );
HX_ASSERT( m_pCondLock && m_pCond);
}
HXUnixEvent::~HXUnixEvent()
{
//Do NOT delete the mutex that the cond makes for us....
HX_DELETE( m_pCond );
m_pCondLock = NULL;
}
HX_RESULT HXUnixEvent::SignalEvent()
{
//Lock it all down.
m_pCondLock->Lock();
//Whether or not this is manual reset, set the state.
m_bEventIsSet = TRUE;
//Signal the event depending on what type it is.
if( m_bIsManualReset )
{
//Manual reset, wake up all threads. All waits become noops
//until the event is reset.
m_pCond->Broadcast();
}
else
{
m_pCond->Signal();
}
//Unlock it and go.
m_pCondLock->Unlock();
return HXR_OK;
}
HX_RESULT HXUnixEvent::Wait( UINT32 uTimeoutPeriod )
{
HX_RESULT res = HXR_OK;
m_pCondLock->Lock();
//Check to see if this event has already been signaled.
if( m_bEventIsSet )
{
//If we are not manual reset and we are signaled. reset the
//signaled flag before returning.
if( !m_bIsManualReset )
{
m_bEventIsSet = FALSE;
}
m_pCondLock->Unlock();
return HXR_OK;
}
//We are not manual reset.
if(uTimeoutPeriod!=ALLFS)
{
//XXXgfw We can be woken up by signals before the event is
//actually signaled or the time has elapsed. Not sure what to
//do in that case yet. Since most implementations try to
//minimize these wakups I will just ignore it for now since we
//are just using condtionals to mimic Window's events.
res = m_pCond->TimedWait(uTimeoutPeriod);
}
else
{
m_pCond->Wait();
}
//Now, if we just woke up and the event had been signaled, We need
//reset the event.
if( !m_bIsManualReset && m_bEventIsSet )
{
m_bEventIsSet = FALSE;
}
//Now that we have waited
m_pCondLock->Unlock();
return res;
}
HX_RESULT HXUnixEvent::ResetEvent()
{
m_pCondLock->Lock();
m_bEventIsSet = FALSE;
m_pCondLock->Unlock();
return HXR_OK;
}
void* HXUnixEvent::GetEventHandle()
{
//XXXgfw This doesn't look like it is used right now. Assuming we
//just want it to be a unique handle to this event, we can use the
//this pointer to the cond class we made.
return (void*)m_pCond;
}
//=======================================================================
//
// HXUnixCondition
// ---------------------
//
//=======================================================================
HXUnixCondition::HXUnixCondition()
{
};
HXUnixCondition::~HXUnixCondition()
{
};
HX_RESULT HXUnixCondition::MakeCondition( HXUnixCondition*& pCond,
HXUnixMutex*& pMutex )
{
HX_ASSERT( pMutex==NULL);
#if defined( _LINUX ) && defined(_UNIX_THREADS_SUPPORTED) || defined(_MAC_UNIX)
pCond = (HXUnixCondition*) new HXPthreadCondition(pMutex);
#elif defined(_SOLARIS)
pCond = (HXUnixCondition*) new HXSolarisCondition(pMutex);
#else
HX_ASSERT( "No unix condtional for this platform" == NULL );
#endif
if(pCond == NULL )
{
HX_ASSERT(0);
return HXR_OUTOFMEMORY;
}
HX_ASSERT( pMutex );
return HXR_OK;
}
HX_RESULT HXUnixCondition::Wait()
{
HX_RESULT ret;
ret = _Wait();
return ret;
}
HX_RESULT HXUnixCondition::TimedWait( UINT32 uTimeoutPeriod )
{
return _TimedWait(uTimeoutPeriod);
}
HX_RESULT HXUnixCondition::Broadcast()
{
return _Broadcast();
}
HX_RESULT HXUnixCondition::Signal()
{
return _Signal();
}
//=======================================================================
//
// HXUnixAsyncTimer
// -----------------------
//
//=======================================================================
//Static data initializers
HXMutex* HXUnixAsyncTimer::m_pmtxMapLock = NULL;
CHXMapLongToObj HXUnixAsyncTimer::m_mapTimers;
//Timeouts are in miliseconds.
HXUnixAsyncTimer::HXUnixAsyncTimer( ULONG32 ulTimeOut, HXThread* pReceivingThread )
: m_ulTimeOut( ulTimeOut ),
m_pReceivingThread( pReceivingThread ),
m_pMessagePump( NULL ),
m_pMsg(NULL),
m_pfExecFunc(NULL)
{
//Make the message to pump.
m_pMsg = new HXThreadMessage( HXMSG_ASYNC_TIMER, (void*)m_ulTimeOut, NULL, NULL );
//Start the thread. We have to do this weird casting because
//the HXThread::MakeThread takes HXThread*&....
HXThread* pTmp = NULL;
HXUnixThread::MakeThread(pTmp);
HX_ASSERT( pTmp );
m_pMessagePump = (HXUnixThread*)pTmp;
m_pMessagePump->CreateThread( _ActualMessagePump, (void*)this );
}
HXUnixAsyncTimer::HXUnixAsyncTimer( ULONG32 ulTimeOut, TIMERPROC pfExecFunc )
: m_ulTimeOut( ulTimeOut ),
m_pReceivingThread(NULL),
m_pMessagePump(NULL),
m_pMsg(NULL),
m_pfExecFunc( pfExecFunc )
{
//we need non-null pfExecFunc
HX_ASSERT( m_pfExecFunc != NULL );
//Start the thread.
HXThread* pTmp = NULL;
HXUnixThread::MakeThread(pTmp);
HX_ASSERT( pTmp );
m_pMessagePump = (HXUnixThread*)pTmp;
m_pMessagePump->CreateThread( _ActualMessagePump, (void*)this );
}
HXUnixAsyncTimer::~HXUnixAsyncTimer()
{
//Tell the message pump to quit.
HXThreadMessage msgQuit(HXMSG_QUIT, NULL, NULL);
m_pMessagePump->PostMessage( &msgQuit );
//Wait for it to stop.
m_pMessagePump->JoinThread();
HX_DELETE( m_pMessagePump );
}
ULONG32 HXUnixAsyncTimer::GetID()
{
ULONG32 ulTmp=0;
m_pMessagePump->GetThreadId(ulTmp);
return ulTmp;
}
//XXXgfw just to keep the below more readable.
#define PARG ((HXUnixAsyncTimer*)pArg)
void* HXUnixAsyncTimer::_ActualMessagePump(void* pArg)
{
while(1)
{
if( HXR_OK == PARG->m_pMessagePump->PeekMessage(&PARG->m_msgTmp))
{
//Got a message. If it is HXMSG_QUIT get our of here.
if( PARG->m_msgTmp.m_ulMessage == HXMSG_QUIT )
{
break;
}
}
microsleep( PARG->m_ulTimeOut*1000 );
if( PARG->m_pMsg != NULL )
PARG->m_pReceivingThread->PostMessage( PARG->m_pMsg);
else
PARG->m_pfExecFunc( 0, 0, PARG->GetID(), GetTickCount() );
}
return NULL;
}
#undef PARG
UINT32 HXUnixAsyncTimer::SetTimer(ULONG32 ulTimeOut, HXThread* pReceivingThread )
{
if( m_pmtxMapLock == NULL )
{
HXMutex::MakeMutex( m_pmtxMapLock );
HX_ASSERT( m_pmtxMapLock );
}
//lock it.
m_pmtxMapLock->Lock();
ULONG32 ulTimerID = 0;
HX_ASSERT( ulTimeOut != 0 );
HX_ASSERT( pReceivingThread != NULL );
HXUnixAsyncTimer* pTimer = new HXUnixAsyncTimer(ulTimeOut, pReceivingThread );
HX_ASSERT( pTimer != NULL );
if( pTimer != NULL )
{
//Add new timer to map.
ulTimerID = pTimer->GetID();
m_mapTimers.SetAt( ulTimerID, (void*)pTimer );
}
//unlock the map.
m_pmtxMapLock->Unlock();
return ulTimerID;
}
UINT32 HXUnixAsyncTimer::SetTimer(ULONG32 ulTimeOut, TIMERPROC pfExecFunc )
{
if( m_pmtxMapLock == NULL )
{
HXMutex::MakeMutex( m_pmtxMapLock );
HX_ASSERT( m_pmtxMapLock );
}
//lock it.
m_pmtxMapLock->Lock();
ULONG32 ulTimerID = 0;
HX_ASSERT( ulTimeOut != 0 );
HX_ASSERT( pfExecFunc != NULL );
HXUnixAsyncTimer* pTimer = new HXUnixAsyncTimer(ulTimeOut, pfExecFunc );
HX_ASSERT( pTimer != NULL );
if( pTimer != NULL )
{
//Add new timer to map.
ulTimerID = pTimer->GetID();
m_mapTimers.SetAt( ulTimerID, (void*)pTimer );
}
//unlock the map.
m_pmtxMapLock->Unlock();
return ulTimerID;
}
BOOL HXUnixAsyncTimer::KillTimer(UINT32 ulTimerID )
{
//lock it.
m_pmtxMapLock->Lock();
BOOL bRetVal = FALSE;
void* pTimer = NULL;
HX_ASSERT( ulTimerID != 0 );
if( m_mapTimers.Lookup( ulTimerID, pTimer ) )
{
//Found it.
bRetVal = TRUE;
HXUnixAsyncTimer* pTmp = (HXUnixAsyncTimer*)pTimer;
HX_DELETE(pTmp);
m_mapTimers.RemoveKey( ulTimerID );
}
//unlock the map.
m_pmtxMapLock->Unlock();
return bRetVal;
}
#endif //_UNIX_THREADS_SUPPORTED
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -