⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 symbianthreads.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    }
    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 + -