📄 symbianthreads.cpp
字号:
}
return retVal;
}
HX_RESULT HXSymbianThread::DispatchMessage(HXThreadMessage* pMsg)
{
HX_ASSERT( "HXSymbianThread::DispatchMessage is not implemented yet." == NULL );
return HXR_FAIL;
}
TInt HXSymbianThread::_ThreadWrapper(TAny* pExecStruct)
{
TInt nRetVal = KErrNone;
st_execStruct* pstExec = (st_execStruct*)pExecStruct;
//Install a handle to the global manager for this thread.
HXGlobalManInstance::SetInstance(pstExec->pGlobalManager);
//Install an active Scheduler for this thread.
CActiveScheduler* pSched = new CActiveScheduler();
CActiveScheduler::Install(pSched);
//Call the thread.
nRetVal = pstExec->pfExecProc(pstExec->pExecArg);
CActiveScheduler::Install(0);
HX_DELETE(pSched);
return nRetVal;
}
//=======================================================================
//
// HXSymbianMutex
// ------------------
//
//=======================================================================
HXSymbianMutex::HXSymbianMutex()
: m_pCritSec(NULL),
m_bInited(FALSE),
m_pCritSecLck(NULL),
m_ulOwnerThread(0),
m_ulLockCount(0)
{
}
HXSymbianMutex::~HXSymbianMutex()
{
if( m_pCritSec )
{
m_pCritSec->Close();
HX_DELETE(m_pCritSec);
}
if( m_pCritSecLck )
{
m_pCritSecLck->Close();
HX_DELETE(m_pCritSecLck);
}
m_bInited = FALSE;
}
HX_RESULT HXSymbianMutex::_Init()
{
TInt err1 = KErrNone;
TInt err2 = KErrNone;
HX_RESULT res = HXR_FAIL;
if( !m_bInited)
{
m_pCritSec = new RCriticalSection;
if( m_pCritSec )
{
err1 = m_pCritSec->CreateLocal();
}
m_pCritSecLck = new RCriticalSection;
if( m_pCritSecLck )
{
err2 = m_pCritSecLck->CreateLocal();
}
}
if( m_pCritSec && m_pCritSecLck && KErrNone==err1 && KErrNone==err2 )
{
res = HXR_OK;
m_bInited = TRUE;
}
return res;
}
HX_RESULT HXSymbianMutex::Lock()
{
HX_RESULT res = HXR_OK;
RThread me;
//XXXgfw I wonder if the check every time is too much of a perf
//hit.
if( !m_bInited )
{
res = _Init();
if( FAILED(res) )
return res;
}
m_pCritSecLck->Wait();
if( m_ulOwnerThread != me.Id() )
{
m_pCritSecLck->Signal();
m_pCritSec->Wait();
m_pCritSecLck->Wait();
m_ulOwnerThread = me.Id();
//Make sure the lock count is always zero when we hand off a
//mutex to another thread. Otherwise there was too many
//unlocks or the like.
HX_ASSERT( m_ulLockCount == 0 );
m_ulLockCount = 1;
}
else
{
//We alread have it locked. Just increment the lock count
m_ulLockCount++;
}
m_pCritSecLck->Signal();
return res;
}
HX_RESULT HXSymbianMutex::Unlock()
{
HX_RESULT res = HXR_OK;
RThread me;
//XXXgfw I wonder if the check every time is too much of a perf
//hit.
if( !m_bInited )
{
res = _Init();
if( FAILED(res) )
return res;
}
m_pCritSecLck->Wait();
HX_ASSERT( m_ulLockCount != 0 && m_ulOwnerThread == me.Id() );
if( m_ulLockCount == 0 || m_ulOwnerThread!=me.Id() )
{
m_pCritSecLck->Signal();
return HXR_FAIL;
}
if( m_ulLockCount == 1 )
{
//We are really done with it. Do the real unlock now.
m_pCritSec->Signal();
m_ulOwnerThread = 0;
m_ulLockCount=0;
}
else
{
m_ulLockCount--;
}
m_pCritSecLck->Signal();
return res;
}
HX_RESULT HXSymbianMutex::Trylock()
{
HX_RESULT res = HXR_OK;
RThread me;
//XXXgfw I wonder if the check every time is too much of a perf
//hit.
if( !m_bInited )
{
res = _Init();
if( FAILED(res) )
return res;
}
m_pCritSecLck->Wait();
if( m_pCritSec->IsBlocked() )
{
//Someone has it.
HX_ASSERT( m_ulOwnerThread != 0 );
HX_ASSERT( m_ulLockCount != 0 );
if( m_ulOwnerThread == me.Id() )
{
//It us.
m_ulLockCount++;
res = HXR_OK;
}
else
{
//We would block on it.
res = HXR_FAIL;
}
}
else
{
//No one has it. grab it now.
HX_ASSERT( m_ulOwnerThread == 0 );
HX_ASSERT( m_ulLockCount == 0 );
m_pCritSec->Wait();
m_ulLockCount=1;
m_ulOwnerThread = me.Id();
res = HXR_OK;
}
m_pCritSecLck->Signal();
return res;
}
//=======================================================================
//
// HXSymbianEvent
// ------------------
//
//=======================================================================
HXSymbianEvent::HXSymbianEvent(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.
//
m_pCond = new RSemaphore();
if( m_pCond )
{
m_pCond->CreateLocal(0);
}
HXMutex* pTmp = NULL;
HXMutex::MakeMutex(pTmp);
m_pCondLock = (HXSymbianMutex*)pTmp;
HX_ASSERT( m_pCondLock && m_pCond );
//We ignore the EventName for now...
}
HXSymbianEvent::~HXSymbianEvent()
{
if( m_pCond )
{
m_pCond->Close();
HX_DELETE( m_pCond );
}
HX_DELETE(m_pCondLock);
}
HX_RESULT HXSymbianEvent::Wait( UINT32 uTimeoutPeriod )
{
HX_RESULT res = HXR_OK;
//Symbian does not support timed waits...
HX_ASSERT( uTimeoutPeriod==ALLFS);
m_pCondLock->Lock();
//Check to see if this event has already been signaled.
if( !m_bEventIsSet )
{
//We must wait on the event then....
m_pCondLock->Unlock();
m_pCond->Wait();
m_pCondLock->Lock();
}
//If we are not manual reset and we are signaled. reset the
//signaled flag before returning otherwise leave it signaled for
//everyone else that comes in to wait.
if( !m_bIsManualReset )
m_bEventIsSet = FALSE;
//Now that we have waited
m_pCondLock->Unlock();
return res;
}
HX_RESULT HXSymbianEvent::ResetEvent()
{
m_pCondLock->Lock();
m_bEventIsSet = FALSE;
m_pCondLock->Unlock();
return HXR_OK;
}
HX_RESULT HXSymbianEvent::SignalEvent()
{
//Lock it all down.
m_pCondLock->Lock();
//Whether or not this is manual reset, set the state.
m_bEventIsSet = TRUE;
//See if anyone is waiting on this event or not...
int nCount = m_pCond->Count();
//Signal the event depending on what type it is.
if( m_bIsManualReset && nCount<0 )
{
//Manual reset, wake up all threads. All waits become noops
//until the event is reset.
//XXXgfw symbian has no 'broadcast' kind of option. We can
//fake it by getting the sem count and calling signal that
//much.
m_pCond->Signal(Abs(nCount));
}
else
{
m_pCond->Signal();
}
//Unlock it and go.
m_pCondLock->Unlock();
return HXR_OK;
}
void* HXSymbianEvent::GetEventHandle()
{
return (void*)m_pCond;
}
//=======================================================================
//
// HXSymbianAsyncTimer
// -----------------------
//
//=======================================================================
UINT32 HXSymbianAsyncTimer::SetTimer(ULONG32 ulTimeOut, HXThread* pReceivingThread )
{
//lock it.
GetMapLock()->Lock();
ULONG32 ulTimerID = 0;
HX_ASSERT( ulTimeOut != 0 );
HX_ASSERT( pReceivingThread != NULL );
HXSymbianAsyncTimerImp* pTimer = CreateTimer();
HX_ASSERT( pTimer != NULL );
if( pTimer != NULL )
{
pTimer->Init(ulTimeOut, pReceivingThread );
//Add new timer to map.
ulTimerID = pTimer->GetID();
GetMapTimers().SetAt( ulTimerID, (void*)pTimer );
}
//unlock the map.
GetMapLock()->Unlock();
return ulTimerID;
}
UINT32 HXSymbianAsyncTimer::SetTimer(ULONG32 ulTimeOut, TIMERPROC pfExecFunc )
{
//lock it.
GetMapLock()->Lock();
ULONG32 ulTimerID = 0;
HX_ASSERT( ulTimeOut != 0 );
HX_ASSERT( pfExecFunc != NULL );
HXSymbianAsyncTimerImp* pTimer = CreateTimer();
HX_ASSERT( pTimer != NULL );
if( pTimer != NULL )
{
pTimer->Init(ulTimeOut, pfExecFunc );
//Add new timer to map.
ulTimerID = pTimer->GetID();
GetMapTimers().SetAt( ulTimerID, (void*)pTimer );
}
//unlock the map.
GetMapLock()->Unlock();
return ulTimerID;
}
BOOL HXSymbianAsyncTimer::KillTimer(UINT32 ulTimerID )
{
//lock it.
GetMapLock()->Lock();
BOOL bRetVal = FALSE;
void* pTimer = NULL;
HX_ASSERT( ulTimerID != 0 );
if( GetMapTimers().Lookup( ulTimerID, pTimer ) )
{
//Found it.
HXSymbianAsyncTimerImp* pTmp = (HXSymbianAsyncTimerImp*)pTimer;
bRetVal = TRUE;
// delete is not used because the timer
// may need to delay it's destruction.
// The Destroy() call hides this detail
pTmp->Destroy();
pTmp = 0;
GetMapTimers().RemoveKey( ulTimerID );
}
//unlock the map.
GetMapLock()->Unlock();
return bRetVal;
}
HXSymbianAsyncTimerImp* HXSymbianAsyncTimer::CreateTimer()
{
HXSymbianAsyncTimerImp* pRet = 0;
#if defined USE_SYMBIAN_THREADS_FOR_ASYNCTIMERS
pRet = new HXSymbianThreadAsyncTimer;
#else
pRet = new HXSymbianRTimerAsyncTimer;
#endif
return pRet;
}
static void DestroyMapLock(GlobalType pObj)
{
HXMutex* pMapLock = (HXMutex*)pObj;
delete pMapLock;
}
HXMutex* HXSymbianAsyncTimer::GetMapLock()
{
static const HXMutex* const z_pMapLock = NULL;
HXGlobalManager* pGM = HXGlobalManager::Instance();
GlobalPtr ptr = pGM->Get(&z_pMapLock);
if (!ptr)
{
HXMutex* pMapLock = 0;
HXMutex::MakeMutex(pMapLock);
ptr = pGM->Add(&z_pMapLock, pMapLock, &DestroyMapLock);
}
return (HXMutex*)(*ptr);
}
CHXMapLongToObj& HXSymbianAsyncTimer::GetMapTimers()
{
static const CHXMapLongToObj* const z_pMapTimers = NULL;
return HXGlobalMapLongToObj::Get(&z_pMapTimers);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -