symbianthreads.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:26k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */
  35. //This is used to turn off threads in libc5 builds.
  36. #include "hxtypes.h"  //for UINT32
  37. #include "hxresult.h" //for HX_RESULT
  38. #include "hxslist.h"
  39. #include "hxassert.h" //for HX_ASSERT
  40. #include "hxmsgs.h"   //for HXMSG_ASYNC_TIMER message.
  41. #include "hxmap.h"    //for CHXMapLongToObj
  42. #include "hxtick.h"   //for GetTickCount()
  43. #include "globals/hxglobals.h"
  44. #include "SymbianThreads.h"
  45. #include "symbian_async_timer_imp.h"
  46. #include "symbian_rtimer_at_imp.h"
  47. #include "symbian_thread_at_imp.h"
  48. #include "hxglobalmgr_inst.h"
  49. //XXXgfw I first coded this to use RTimers for RunL callbacks to get
  50. //the work of the async timer done. But, if the thread that creates
  51. //the timer blocks at all we stop getting callbacks. I think now that
  52. //this may cause problems with the way Helix uses the timers. So, I am
  53. //going to code a version that uses real threads to get the work
  54. //done. You can use the below define to build either one you want.
  55. //#define  USE_SYMBIAN_THREADS_FOR_ASYNCTIMERS
  56. //=======================================================================
  57. //
  58. //                      HXSymbianThread
  59. //                   ------------------
  60. //
  61. //=======================================================================
  62. HXSymbianThread::HXSymbianThread()
  63.     : m_pThread(NULL),
  64.       m_pSemMessageCount(NULL),
  65.       m_pmtxQue(NULL)
  66. {
  67.     TInt err;
  68.     m_pSemMessageCount = new RSemaphore();
  69.     HX_ASSERT( m_pSemMessageCount );
  70.     if( m_pSemMessageCount )
  71.     {
  72.         err = m_pSemMessageCount->CreateLocal(0);
  73.         if( KErrNone != err )
  74.         {
  75.             HX_DELETE( m_pSemMessageCount );
  76.         }
  77.     }
  78.     
  79.     HXMutex::MakeMutex( m_pmtxQue );
  80.     HX_ASSERT( m_pmtxQue );
  81. }
  82. HXSymbianThread::~HXSymbianThread()
  83. {
  84.     //Clean up message que.
  85.     while( !m_messageQue.IsEmpty() )
  86.     {
  87.         HXThreadMessage* pTmp = (HXThreadMessage *)(m_messageQue.RemoveHead());
  88.         HX_DELETE( pTmp );
  89.     }
  90.     if( m_pSemMessageCount)
  91.     {
  92.         m_pSemMessageCount->Close();
  93.         HX_DELETE( m_pSemMessageCount );
  94.     }
  95.     
  96.     HX_DELETE( m_pmtxQue );
  97.     if( m_pThread )
  98.     {
  99.         m_pThread->Kill(0);
  100.         m_pThread->Close();
  101.         HX_DELETE(m_pThread);
  102.     }
  103. }
  104. HX_RESULT HXSymbianThread::CreateThread( void*(pfExecFunc(void*)),
  105.                                          void* pArg,
  106.                                          ULONG32 ulCreationFlags)
  107. {
  108.     HX_RESULT retVal = HXR_OK;
  109.     TInt      err    = KErrNone;
  110.     
  111.     HX_ASSERT( NULL==m_pThread );
  112.     if( NULL != m_pThread )
  113.     {
  114.         retVal = HXR_UNEXPECTED;
  115.     }
  116.     else
  117.     {
  118.         m_pThread = new RThread();
  119.         if( NULL == m_pThread )
  120.         {
  121.             retVal = HXR_FAIL;
  122.         }
  123.         else
  124.         {
  125.             //Each thread has to have a unique name. Oh bother.
  126.             //Lets just use the heap pointer.
  127.             char szBuff[20]; /* Flawfinder: ignore */
  128.             sprintf( szBuff, "%p", m_pThread ); /* Flawfinder: ignore */
  129.             TPtr ThreadName((unsigned short*)szBuff, strlen(szBuff), 20);
  130.             st_execStruct stExecStruct;
  131.             stExecStruct.pfExecProc     = (TThreadFunction)pfExecFunc;
  132.             stExecStruct.pExecArg       = pArg;
  133.             stExecStruct.pGlobalManager = HXGlobalManInstance::GetInstance();
  134.             
  135.             err = m_pThread->Create( ThreadName, 
  136.                                      _ThreadWrapper,
  137.                                      KDefaultStackSize,
  138.                                      &User::Heap(), //Use parent HEAP
  139.                                      &stExecStruct 
  140.                                      );
  141.             if( KErrNone != err )
  142.             {
  143.                 //Could not start thread.
  144.                 retVal = HXR_FAIL;
  145.                 m_pThread->Close();
  146.                 HX_DELETE( m_pThread );
  147.             }
  148.             else
  149.             {
  150.                 //Tell the system we want to be notifed when this
  151.                 //thread terminates for any reason.
  152.                 m_pThread->Logon(m_reqStat);
  153.                 //Symbian threads start up in a 'suspended' mode. HXThreads
  154.                 //assume that the threads are running from the get go. So, we
  155.                 //do a resume here.
  156.                 m_pThread->Resume();
  157.             }
  158.         }
  159.     }
  160.     return retVal;
  161. }
  162. HX_RESULT HXSymbianThread::Exit(UINT32 unExitCode)
  163. {
  164.     if( NULL==m_pThread )
  165.     {
  166.         //Thread has already gone or was never here.
  167.         return HXR_UNEXPECTED;
  168.     }
  169.     
  170.     if( m_pThread->Id() != (TThreadId)GetCurrentThreadID() )
  171.     {
  172.         //Ok, because of the way winthrd.cpp does it, this call also
  173.         //acts as a 'pthread_join' when the calling thread isn't the
  174.         //m_threadID.
  175.         
  176.         //Also, it looks like this method isn't set up to look at the
  177.         //return value of the thread. We could return HXR_FAIL is it
  178.         //is anything except 0 but for now just throw it away.
  179.         User::WaitForRequest(m_reqStat);
  180.     }
  181.     else
  182.     {
  183.         //Kill our selves....
  184.         m_pThread->Kill(unExitCode);
  185.     }
  186.     
  187.     return HXR_OK;
  188. }
  189. HX_RESULT HXSymbianThread::SetPriority( UINT32 ulPriority)
  190. {
  191.     HX_RESULT res = HXR_FAIL;
  192.     if( m_pThread)
  193.     {
  194.         m_pThread->SetPriority((TThreadPriority)ulPriority);
  195.         res = HXR_OK;
  196.     }
  197.     return res;
  198. }
  199. HX_RESULT HXSymbianThread::GetPriority( UINT32& ulPriority)
  200. {
  201.     HX_RESULT res = HXR_FAIL;
  202.     if( m_pThread)
  203.     {
  204.         ulPriority = m_pThread->Priority();
  205.         res = HXR_OK;
  206.     }
  207.     return res;
  208. }
  209. HX_RESULT HXSymbianThread::YieldTimeSlice()
  210. {
  211.     //Just sleep for a tiny amount so someone else can
  212.     //run.
  213.     User::After(10);
  214.     return HXR_OK;
  215. }
  216. HX_RESULT HXSymbianThread::GetThreadId(UINT32& ulThreadId)
  217. {
  218.     HX_RESULT res = HXR_FAIL;
  219.     if( m_pThread )
  220.     {
  221.         ulThreadId = m_pThread->Id();
  222.         res = HXR_OK;
  223.     }
  224.     
  225.     return res;
  226. }
  227. ULONG32 HXSymbianThread::GetCurrentThreadID()
  228. {
  229.     return RThread().Id();
  230. }
  231. HX_RESULT HXSymbianThread::Suspend()
  232. {
  233.     HX_RESULT res = HXR_FAIL;
  234.     if( m_pThread )
  235.     {
  236.         m_pThread->Suspend();
  237.         res = HXR_OK;
  238.     }
  239.     
  240.     return res;
  241. }
  242. HX_RESULT HXSymbianThread::Resume()
  243. {
  244.     HX_RESULT res = HXR_FAIL;
  245.     if( m_pThread )
  246.     {
  247.         m_pThread->Resume();
  248.         res = HXR_OK;
  249.     }
  250.     
  251.     return res;
  252. }
  253. HX_RESULT HXSymbianThread::PostMessage(HXThreadMessage* pMsg, void* pWindowHandle)
  254. {
  255.     HX_RESULT retVal = HXR_OK;
  256.     
  257.     //Assert that we don't use pWindowHandle. 
  258.     HX_ASSERT( pWindowHandle == NULL );
  259.     
  260.     //To mimic the windows PostMessage we must COPY the pMsg and put
  261.     //it on our que. pMsg is going to go out of scope most likely
  262.     if( NULL != pMsg )
  263.     {
  264.         HXThreadMessage *pMsgTmp = new HXThreadMessage(pMsg);
  265.         if( pMsgTmp == NULL )
  266.         {
  267.             retVal = HXR_OUTOFMEMORY;
  268.         }
  269.         else
  270.         {
  271.             //Lock the mutex protecting the message que.
  272.             m_pmtxQue->Lock();
  273.             
  274.             m_messageQue.AddTail((void*)pMsgTmp);
  275.             
  276.             //If we were empty the the GetMessage thread could have
  277.             //been waiting on us to post. Signal it.
  278.             m_pSemMessageCount->Signal(); 
  279.             m_pmtxQue->Unlock();
  280.         }
  281.     }
  282.     
  283.     return retVal;
  284. }
  285. HX_RESULT HXSymbianThread::GetMessage( HXThreadMessage* pMsg, 
  286.                                      UINT32 ulMsgFilterMin, 
  287.                                      UINT32 ulMsgFilterMax)
  288. {
  289.     HX_RESULT retVal = HXR_OK;
  290.     //assert that ulMsgFilterMax/Min is zero as we don't support it yet.
  291.     HX_ASSERT( ulMsgFilterMax == 0 && ulMsgFilterMin == 0 );
  292.     HX_ASSERT( pMsg );
  293.     
  294.     //We must pop the next message, COPY it into pMsg and delete our copy.
  295.     if( pMsg != NULL )
  296.     {
  297.         //Wait until there is a message.
  298.         m_pSemMessageCount->Wait();
  299.         
  300.         //Protect the que.
  301.         m_pmtxQue->Lock();
  302.         //Sanity check.
  303.         HX_ASSERT( !m_messageQue.IsEmpty() );
  304.         
  305.         HXThreadMessage* pMsgTmp = (HXThreadMessage*)m_messageQue.RemoveHead();
  306.         if( pMsgTmp != NULL )
  307.         {
  308.             pMsg->m_ulMessage             = pMsgTmp->m_ulMessage; 
  309.             pMsg->m_pParam1               = pMsgTmp->m_pParam1; 
  310.             pMsg->m_pParam2               = pMsgTmp->m_pParam2;
  311.             pMsg->m_pPlatformSpecificData = pMsgTmp->m_pPlatformSpecificData;
  312.             
  313.             //free it.
  314.             HX_DELETE( pMsgTmp );
  315.         }
  316.         else
  317.         {
  318.             HX_ASSERT( "que panic" == NULL );
  319.         }
  320.         m_pmtxQue->Unlock();
  321.     }
  322.     
  323.     return retVal;
  324. }
  325. HX_RESULT HXSymbianThread::PeekMessageMatching( HXThreadMessage* pMsg,
  326.                                               HXThreadMessage* pMatch,
  327.                                               BOOL bRemoveMessage )
  328. {
  329.     HX_RESULT retVal = HXR_OK;
  330.         
  331.     HX_ASSERT( pMsg );
  332.     HX_ASSERT( pMatch );
  333.      
  334.     if( pMsg != NULL && pMatch!=NULL )
  335.     {
  336.         //Protect the que.
  337.         m_pmtxQue->Lock();
  338.         //Sanity check.
  339.         if( !m_messageQue.IsEmpty() )
  340.         {
  341.             HXThreadMessage* pMsgTmp = NULL;
  342.             //Loop throught the messages and find a matching
  343.             //one.
  344.             BOOL bSkipMessage  = (pMatch->m_ulMessage==0);
  345.             BOOL bSkipParam1   = (pMatch->m_pParam1==NULL);
  346.             BOOL bSkipParam2   = (pMatch->m_pParam2==NULL);
  347.             BOOL bSkipPlatform = (pMatch->m_pPlatformSpecificData==NULL);
  348.             CHXSimpleList::Iterator i;
  349.             
  350.             for( i=m_messageQue.Begin(); i!=m_messageQue.End(); ++i)
  351.             {
  352.                 pMsgTmp = (HXThreadMessage*)(*i);
  353.                 //Does it match?
  354.                 if( bSkipMessage || pMatch->m_ulMessage==pMsgTmp->m_ulMessage )
  355.                     if( bSkipParam1 || pMatch->m_pParam1==pMsgTmp->m_pParam1 )
  356.                         if( bSkipParam2 || pMatch->m_pParam2==pMsgTmp->m_pParam2 )
  357.                             if( bSkipPlatform || pMatch->m_pPlatformSpecificData==pMsgTmp->m_pPlatformSpecificData )
  358.                                 break;
  359.             }
  360.             //Did we find a match?
  361.             if( i != m_messageQue.End())
  362.             {
  363.                 //We found one!
  364.                 pMsg->m_ulMessage             = pMsgTmp->m_ulMessage; 
  365.                 pMsg->m_pParam1               = pMsgTmp->m_pParam1; 
  366.                 pMsg->m_pParam2               = pMsgTmp->m_pParam2;
  367.                 pMsg->m_pPlatformSpecificData = pMsgTmp->m_pPlatformSpecificData;
  368.                 
  369.                 //Only free it if we removed it from the queue.
  370.                 if( bRemoveMessage )
  371.                 {
  372.                     //XXXgfw That has to be a better way than this. We
  373.                     //have the iterator up above. How do you delete with
  374.                     //one.
  375.                     LISTPOSITION listpos = m_messageQue.Find(pMsgTmp);
  376.                     HX_ASSERT( listpos );
  377.                     if(listpos)
  378.                     {
  379.                         m_messageQue.RemoveAt(listpos);
  380.                     }
  381.                     HX_DELETE( pMsgTmp );
  382.                 }
  383.             }
  384.             else
  385.             {
  386.                 retVal=HXR_FAIL;
  387.             }
  388.         }
  389.         else
  390.         {
  391.             //There was no message to get
  392.             retVal=HXR_FAIL;
  393.         }
  394.         m_pmtxQue->Unlock();
  395.     }
  396.     return retVal;
  397. }
  398. HX_RESULT HXSymbianThread::PeekMessage( HXThreadMessage* pMsg,
  399.                                       UINT32 ulMsgFilterMin,
  400.                                       UINT32 ulMsgFilterMax,
  401.                                       BOOL   bRemoveMessage
  402.                                       )
  403. {
  404.     HX_RESULT retVal = HXR_OK;
  405.     //assert that ulMsgFilterMax/Min is zero as we don't support it yet.
  406.     HX_ASSERT( ulMsgFilterMax == 0 && ulMsgFilterMin == 0 );
  407.     HX_ASSERT( pMsg );
  408.     
  409.     //We must pop the next message, COPY it into pMsg and delete our copy.
  410.     if( pMsg != NULL ) 
  411.     {
  412.         //Protect the que.
  413.         m_pmtxQue->Lock();
  414.         //Sanity check.
  415.         if( !m_messageQue.IsEmpty() )
  416.         {
  417.             HXThreadMessage* pMsgTmp = NULL;
  418.             //Do we romove the message or peek at it?
  419.             if( bRemoveMessage )
  420.             {
  421.                 pMsgTmp = (HXThreadMessage*)m_messageQue.RemoveHead();
  422.             }
  423.             else
  424.             {
  425.                 pMsgTmp = (HXThreadMessage*)m_messageQue.GetHead();
  426.             }
  427.                 
  428.             if( pMsgTmp != NULL )
  429.             {
  430.                 pMsg->m_ulMessage             = pMsgTmp->m_ulMessage; 
  431.                 pMsg->m_pParam1               = pMsgTmp->m_pParam1; 
  432.                 pMsg->m_pParam2               = pMsgTmp->m_pParam2;
  433.                 pMsg->m_pPlatformSpecificData = pMsgTmp->m_pPlatformSpecificData;
  434.                 
  435.                 //Only free it if we removed it from the queue.
  436.                 if( bRemoveMessage )
  437.                     HX_DELETE( pMsgTmp );
  438.             }
  439.             else
  440.             {
  441.                 HX_ASSERT( "que panic" == NULL );
  442.             }
  443.         }
  444.         else
  445.         {
  446.             //There was no message to get
  447.             retVal=HXR_FAIL;
  448.         }
  449.         m_pmtxQue->Unlock();
  450.     }
  451.     return retVal;
  452. }
  453. HX_RESULT HXSymbianThread::DispatchMessage(HXThreadMessage* pMsg)
  454. {
  455.     HX_ASSERT( "HXSymbianThread::DispatchMessage is not implemented yet." == NULL );
  456.     return HXR_FAIL;
  457. }
  458. TInt HXSymbianThread::_ThreadWrapper(TAny* pExecStruct)
  459. {
  460.     TInt nRetVal = KErrNone;
  461.     
  462.     st_execStruct* pstExec = (st_execStruct*)pExecStruct;
  463.     
  464.     //Install a handle to the global manager for this thread.
  465.     HXGlobalManInstance::SetInstance(pstExec->pGlobalManager);
  466.     
  467.     //Install an active Scheduler for this thread.
  468.     CActiveScheduler* pSched = new CActiveScheduler();
  469.     CActiveScheduler::Install(pSched);
  470.     
  471.     //Call the thread.
  472.     nRetVal =  pstExec->pfExecProc(pstExec->pExecArg);
  473.     CActiveScheduler::Install(0);
  474.     HX_DELETE(pSched);
  475.     
  476.     return nRetVal;
  477. }
  478. //=======================================================================
  479. //
  480. //                      HXSymbianMutex
  481. //                   ------------------
  482. //
  483. //=======================================================================
  484. HXSymbianMutex::HXSymbianMutex()
  485.     : m_pCritSec(NULL),
  486.       m_bInited(FALSE),
  487.       m_pCritSecLck(NULL),
  488.       m_ulOwnerThread(0),
  489.       m_ulLockCount(0)
  490. {
  491. }
  492.     
  493. HXSymbianMutex::~HXSymbianMutex()
  494. {
  495.     if( m_pCritSec )
  496.     {
  497.         m_pCritSec->Close();
  498.         HX_DELETE(m_pCritSec);
  499.     }
  500.     if( m_pCritSecLck )
  501.     {
  502.         m_pCritSecLck->Close();
  503.         HX_DELETE(m_pCritSecLck);
  504.     }
  505.     m_bInited = FALSE;
  506. }
  507. HX_RESULT HXSymbianMutex::_Init()
  508. {
  509.     TInt      err1 = KErrNone;
  510.     TInt      err2 = KErrNone;
  511.     HX_RESULT res  = HXR_FAIL;
  512.     
  513.     if( !m_bInited)
  514.     {
  515.         m_pCritSec = new RCriticalSection;
  516.         if( m_pCritSec )
  517.         {
  518.             err1 = m_pCritSec->CreateLocal();
  519.         }
  520.         m_pCritSecLck = new RCriticalSection;
  521.         if( m_pCritSecLck )
  522.         {
  523.             err2 = m_pCritSecLck->CreateLocal();
  524.         }
  525.     }
  526.     if( m_pCritSec && m_pCritSecLck && KErrNone==err1 && KErrNone==err2 )
  527.     {
  528.         res = HXR_OK;
  529.         m_bInited = TRUE;
  530.     }
  531.     return res;
  532. }
  533. HX_RESULT HXSymbianMutex::Lock()
  534. {
  535.     HX_RESULT res = HXR_OK;
  536.     RThread   me;
  537.     
  538.     //XXXgfw I wonder if the check every time is too much of a perf
  539.     //hit.
  540.     if( !m_bInited )
  541.     {
  542.         res = _Init();
  543.         if( FAILED(res) )
  544.             return res;
  545.     }
  546.     m_pCritSecLck->Wait();
  547.     if( m_ulOwnerThread != me.Id() )
  548.     {
  549.         m_pCritSecLck->Signal();
  550.         m_pCritSec->Wait();
  551.         m_pCritSecLck->Wait();
  552.         m_ulOwnerThread = me.Id();
  553.         //Make sure the lock count is always zero when we hand off a
  554.         //mutex to another thread. Otherwise there was too many
  555.         //unlocks or the like.
  556.         HX_ASSERT( m_ulLockCount == 0 );
  557.         m_ulLockCount   = 1;
  558.     }
  559.     else
  560.     {
  561.         //We alread have it locked. Just increment the lock count
  562.         m_ulLockCount++;
  563.     }
  564.     m_pCritSecLck->Signal();
  565.     return res;
  566. }
  567.     
  568. HX_RESULT HXSymbianMutex::Unlock()
  569. {
  570.     HX_RESULT res = HXR_OK;
  571.     RThread me;
  572.     
  573.     //XXXgfw I wonder if the check every time is too much of a perf
  574.     //hit.
  575.     if( !m_bInited )
  576.     {
  577.         res = _Init();
  578.         if( FAILED(res) )
  579.             return res;
  580.     }
  581.     m_pCritSecLck->Wait();
  582.     HX_ASSERT( m_ulLockCount != 0 && m_ulOwnerThread == me.Id() );
  583.     if( m_ulLockCount == 0 || m_ulOwnerThread!=me.Id() )
  584.     {
  585.         m_pCritSecLck->Signal();
  586.         return HXR_FAIL;
  587.     }
  588.     
  589.     if( m_ulLockCount == 1 )
  590.     {
  591.         //We are really done with it. Do the real unlock now.
  592.         m_pCritSec->Signal();
  593.         m_ulOwnerThread = 0;
  594.         m_ulLockCount=0;
  595.     }
  596.     else
  597.     {
  598.         m_ulLockCount--;
  599.     }
  600.     m_pCritSecLck->Signal();
  601.     return res;
  602. }
  603.     
  604. HX_RESULT HXSymbianMutex::Trylock()
  605. {
  606.     HX_RESULT res = HXR_OK;
  607.     RThread me;
  608.     
  609.     //XXXgfw I wonder if the check every time is too much of a perf
  610.     //hit.
  611.     if( !m_bInited )
  612.     {
  613.         res = _Init();
  614.         if( FAILED(res) )
  615.             return res;
  616.     }
  617.     m_pCritSecLck->Wait();
  618.     if( m_pCritSec->IsBlocked() )
  619.     {
  620.         //Someone has it.
  621.         HX_ASSERT( m_ulOwnerThread != 0 );
  622.         HX_ASSERT( m_ulLockCount != 0 );
  623.         if( m_ulOwnerThread == me.Id() )
  624.         {
  625.             //It us.
  626.             m_ulLockCount++;
  627.             res = HXR_OK;
  628.         }
  629.         else
  630.         {
  631.             //We would block on it.
  632.             res = HXR_FAIL;
  633.         }
  634.     }
  635.     else
  636.     {
  637.         //No one has it. grab it now.
  638.         HX_ASSERT( m_ulOwnerThread == 0 );
  639.         HX_ASSERT( m_ulLockCount == 0 );
  640.         m_pCritSec->Wait();
  641.         m_ulLockCount=1;
  642.         m_ulOwnerThread = me.Id();
  643.         res = HXR_OK;
  644.     }
  645.     m_pCritSecLck->Signal();
  646.     
  647.     return res;
  648. }
  649. //=======================================================================
  650. //
  651. //                     HXSymbianEvent
  652. //                  ------------------
  653. //
  654. //=======================================================================   
  655. HXSymbianEvent::HXSymbianEvent(const char* pEventName, BOOL bManualReset)
  656.     : m_bIsManualReset( bManualReset ),
  657.       m_bEventIsSet(FALSE),
  658.       m_pCondLock(NULL),
  659.       m_pCond(NULL)
  660. {
  661.     //
  662.     //  NOTE: Because of the way the windows Cond vars work we have:
  663.     //
  664.     //   bManualReset==1  Once we signal once, all other signal/wait
  665.     //                    calls are noops. All threads awake.
  666.     //   bManualReset==0  Once signaled we retain until someone Waits.
  667.     //                    Once someone waits, only one thread wakes up
  668.     //                    and the signal is reset.
  669.     //
  670.     m_pCond = new RSemaphore();
  671.     if( m_pCond )
  672.     {
  673.         m_pCond->CreateLocal(0);
  674.     }
  675.     HXMutex* pTmp =  NULL;
  676.     HXMutex::MakeMutex(pTmp);
  677.     m_pCondLock = (HXSymbianMutex*)pTmp;
  678.     HX_ASSERT( m_pCondLock && m_pCond );
  679.     //We ignore the EventName for now...
  680. }
  681. HXSymbianEvent::~HXSymbianEvent()
  682. {
  683.     if( m_pCond )
  684.     {
  685.         m_pCond->Close();
  686.         HX_DELETE( m_pCond );
  687.     }
  688.     HX_DELETE(m_pCondLock);
  689. }
  690. HX_RESULT HXSymbianEvent::Wait( UINT32 uTimeoutPeriod )
  691. {
  692.     HX_RESULT res = HXR_OK;
  693.     //Symbian does not support timed waits...
  694.     HX_ASSERT( uTimeoutPeriod==ALLFS);
  695.     m_pCondLock->Lock();
  696.     
  697.     //Check to see if this event has already been signaled.
  698.     if( !m_bEventIsSet )
  699.     {
  700.         //We must wait on the event then....
  701.         m_pCondLock->Unlock();
  702.         m_pCond->Wait();
  703.         m_pCondLock->Lock();
  704.     }
  705.     //If we are not manual reset and we are signaled. reset the
  706.     //signaled flag before returning otherwise leave it signaled for
  707.     //everyone else that comes in to wait.
  708.     if( !m_bIsManualReset )
  709.         m_bEventIsSet = FALSE;
  710.     
  711.     //Now that we have waited
  712.     m_pCondLock->Unlock();
  713.     return res;
  714. }
  715. HX_RESULT HXSymbianEvent::ResetEvent()
  716. {
  717.     m_pCondLock->Lock();
  718.     m_bEventIsSet = FALSE;
  719.     m_pCondLock->Unlock();
  720.     return HXR_OK;
  721. }
  722. HX_RESULT HXSymbianEvent::SignalEvent()
  723. {
  724.     //Lock it all down.
  725.     m_pCondLock->Lock();
  726.     //Whether or not this is manual reset, set the state.
  727.     m_bEventIsSet = TRUE;
  728.     //See if anyone is waiting on this event or not...
  729.     int nCount = m_pCond->Count();
  730.     //Signal the event depending on what type it is.
  731.     if( m_bIsManualReset && nCount<0 )
  732.     {
  733.         //Manual reset, wake up all threads. All waits become noops
  734.         //until the event is reset.
  735.         
  736.         //XXXgfw symbian has no 'broadcast' kind of option. We can
  737.         //fake it by getting the sem count and calling signal that
  738.         //much.
  739.         m_pCond->Signal(Abs(nCount));
  740.     }
  741.     else
  742.     {
  743.         m_pCond->Signal();
  744.     }
  745.     
  746.     //Unlock it and go.
  747.     m_pCondLock->Unlock();
  748.     return HXR_OK;
  749. }
  750. void* HXSymbianEvent::GetEventHandle()
  751. {
  752.     return (void*)m_pCond;
  753. }
  754. //=======================================================================
  755. //
  756. //                     HXSymbianAsyncTimer
  757. //                  -----------------------
  758. //
  759. //=======================================================================   
  760. UINT32 HXSymbianAsyncTimer::SetTimer(ULONG32 ulTimeOut, HXThread* pReceivingThread )
  761. {
  762.     //lock it.
  763.     GetMapLock()->Lock();
  764.     ULONG32 ulTimerID = 0;
  765.     
  766.     HX_ASSERT( ulTimeOut != 0 );
  767.     HX_ASSERT( pReceivingThread != NULL );
  768.     
  769.     HXSymbianAsyncTimerImp* pTimer = CreateTimer();
  770.     HX_ASSERT( pTimer != NULL );
  771.     if( pTimer != NULL )
  772.     {
  773. pTimer->Init(ulTimeOut, pReceivingThread );
  774.         //Add new timer to map.
  775.         ulTimerID = pTimer->GetID();
  776.         GetMapTimers().SetAt( ulTimerID, (void*)pTimer );    
  777.     }
  778.     
  779.     //unlock the map.
  780.     GetMapLock()->Unlock();
  781.     return ulTimerID;
  782. }
  783. UINT32 HXSymbianAsyncTimer::SetTimer(ULONG32 ulTimeOut, TIMERPROC pfExecFunc )
  784. {
  785.     //lock it.
  786.     GetMapLock()->Lock();
  787.     ULONG32 ulTimerID = 0;
  788.     
  789.     HX_ASSERT( ulTimeOut != 0 );
  790.     HX_ASSERT( pfExecFunc != NULL );
  791.     
  792.     HXSymbianAsyncTimerImp* pTimer = CreateTimer();
  793.     HX_ASSERT( pTimer != NULL );
  794.     if( pTimer != NULL )
  795.     {
  796. pTimer->Init(ulTimeOut, pfExecFunc );
  797.         //Add new timer to map.
  798.         ulTimerID = pTimer->GetID();
  799.         GetMapTimers().SetAt( ulTimerID, (void*)pTimer );    
  800.     }
  801.     
  802.     //unlock the map.
  803.     GetMapLock()->Unlock();
  804.     return ulTimerID;
  805. }
  806. BOOL HXSymbianAsyncTimer::KillTimer(UINT32 ulTimerID )
  807. {
  808.     //lock it.
  809.     GetMapLock()->Lock();
  810.     BOOL  bRetVal = FALSE;
  811.     void* pTimer  = NULL;
  812.     HX_ASSERT( ulTimerID != 0 );
  813.     
  814.     if( GetMapTimers().Lookup( ulTimerID, pTimer ) )
  815.     {
  816.         //Found it.
  817.         HXSymbianAsyncTimerImp* pTmp = (HXSymbianAsyncTimerImp*)pTimer;
  818.         bRetVal = TRUE;
  819. // delete is not used because the timer
  820. // may need to delay it's destruction.
  821. // The Destroy() call hides this detail
  822.         pTmp->Destroy(); 
  823. pTmp = 0;
  824.         GetMapTimers().RemoveKey( ulTimerID );
  825.     }
  826.     //unlock the map.
  827.     GetMapLock()->Unlock();
  828.     return bRetVal;
  829. }
  830. HXSymbianAsyncTimerImp* HXSymbianAsyncTimer::CreateTimer()
  831. {
  832.     HXSymbianAsyncTimerImp* pRet = 0;
  833. #if defined USE_SYMBIAN_THREADS_FOR_ASYNCTIMERS
  834.     pRet = new HXSymbianThreadAsyncTimer;
  835. #else
  836.     pRet = new HXSymbianRTimerAsyncTimer;
  837. #endif
  838.     return pRet;
  839. }
  840. static void DestroyMapLock(GlobalType pObj)
  841. {
  842.     HXMutex* pMapLock = (HXMutex*)pObj;
  843.     delete pMapLock;
  844. }
  845. HXMutex* HXSymbianAsyncTimer::GetMapLock()
  846. {
  847.     static const HXMutex* const z_pMapLock = NULL;
  848.     HXGlobalManager* pGM = HXGlobalManager::Instance();
  849.     GlobalPtr ptr = pGM->Get(&z_pMapLock);
  850.     if (!ptr)
  851.     {
  852. HXMutex* pMapLock = 0;
  853. HXMutex::MakeMutex(pMapLock);
  854. ptr = pGM->Add(&z_pMapLock, pMapLock, &DestroyMapLock);
  855.     }
  856.     return  (HXMutex*)(*ptr);
  857. }
  858. CHXMapLongToObj& HXSymbianAsyncTimer::GetMapTimers()
  859. {
  860.     static const CHXMapLongToObj* const z_pMapTimers = NULL;
  861.     return HXGlobalMapLongToObj::Get(&z_pMapTimers);
  862. }