carbthrd.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:20k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: carbthrd.cpp,v 1.4.32.3 2004/07/09 01:43:21 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #if defined(_CARBON) || defined(_MAC_UNIX)
  50. #include "platform/mac/carbthrd.h"
  51. #include "hxmsgs.h" //for HXMSG_ASYNC_TIMER message.
  52. HXCarbonThread::HXCarbonThread()
  53.   : m_mpTaskID(NULL)
  54.   , m_mpQueueID(NULL)
  55.   , m_pQueueMutex(NULL)
  56.   , m_pQueuePostSemaphore(kInvalidID)
  57.   , m_mpInternalTerminationNotificationQueueID(NULL)
  58. {
  59.     // xxxbobclark there's a kludgey main app thread wrapper thingie
  60.     // for handling networked threading. It's a case where an
  61.     // HXCarbonThread gets used without HXCarbonThread::CreateThread()
  62.     // being called... but it requires m_mpQueueID. So we create it in
  63.     // the ctor.
  64.     HXMutex::MakeMutex(m_pQueueMutex);
  65.     ::MPCreateSemaphore(INT_MAX, 0, &m_pQueuePostSemaphore);
  66.     OSStatus osResult = MPCreateQueue(&m_mpQueueID);
  67. }
  68. HXCarbonThread::~HXCarbonThread()
  69. {
  70.     this->Exit(0);
  71.     
  72.     // xxxbobclark should I remove the queue here if it exists?
  73.     HX_ASSERT(m_mpQueueID == NULL);
  74.     HX_ASSERT(m_mpTaskID == NULL);
  75.     HX_ASSERT(m_pQueueMutex == NULL);
  76.     HX_ASSERT(m_pQueuePostSemaphore == kInvalidID);
  77. }
  78. HX_RESULT
  79. HXCarbonThread::CreateThread( void* (pExecAddr(void*)), void* pArg, ULONG32 ulCreationFlags )
  80. {
  81.     HX_ASSERT(m_mpTaskID == NULL);
  82.     
  83.     HX_RESULT retval = HXR_OK;
  84.     
  85.     MPTaskOptions options = 0;
  86.     
  87.     if (ulCreationFlags & HX_CREATE_SUSPENDED)
  88.     {
  89. options |= 1;
  90.     }
  91.     
  92.     OSStatus osResult = MPCreateQueue(&m_mpInternalTerminationNotificationQueueID);
  93.     
  94.     if (osResult == noErr)
  95.     {
  96. osResult = MPCreateTask((TaskProc)pExecAddr, pArg, 0, m_mpInternalTerminationNotificationQueueID, NULL, NULL, options, &m_mpTaskID);
  97.     }
  98.     
  99.     if (osResult != noErr) retval = HXR_FAIL;
  100.     
  101.     return retval;
  102. }
  103. HX_RESULT
  104. HXCarbonThread::Suspend(void)
  105. {
  106.     HX_RESULT retval = HXR_NOTIMPL;
  107.     
  108.     // xxxbobclark this is actually why interrupt-like callbacks are impossible
  109.     // to simulate correctly under OS X: there's no suspend or resume available
  110.     // in the MPTask API. I may need to grab the corresponding pthread and tell
  111.     // it to suspend if the pthread API supports it.
  112.     HX_ASSERT(!"Unimplemented Suspend!");
  113.     return retval;
  114. }
  115. HX_RESULT
  116. HXCarbonThread::Resume(void)
  117. {
  118.     HX_RESULT retval = HXR_NOTIMPL;
  119.     HX_ASSERT(!"Unimplemented Resume!");
  120.     return retval;
  121. }
  122. HX_RESULT
  123. HXCarbonThread::SetPriority(UINT32 ulPriority)
  124. {
  125.     HX_RESULT retval = HXR_OK;
  126.     
  127.     OSStatus osStatus = MPSetTaskWeight(m_mpTaskID, ulPriority);
  128.     
  129.     return retval;
  130. }
  131. HX_RESULT
  132. HXCarbonThread::GetPriority(UINT32& ulPriority)
  133. {
  134.     HX_RESULT retval = HXR_NOTIMPL;
  135.     HX_ASSERT(!"Unimplemented GetPriority!");
  136.     return retval;
  137. }
  138. HX_RESULT
  139. HXCarbonThread::YieldTimeSlice(void)
  140. {
  141.     // unnecessary with MPTask implementation on Carbon.
  142.     
  143.     // I'll call MPYield anyway, although the MP API SDK
  144.     // says "In most cases you should not need to call
  145.     // this function".
  146.     
  147.     HX_RESULT retval = HXR_OK;
  148.     MPYield();
  149.     return retval;
  150. }
  151. HX_RESULT
  152. HXCarbonThread::Exit(UINT32 ulExitCode)
  153. {
  154.     // xxxbobclark MPExit must be called from within the 
  155.     // MPTask. That's why I think we need to use MPTerminateTask here.
  156.     
  157.     // This is also called by the destructor, just in case
  158.     
  159.     HX_RESULT retval = HXR_OK;
  160.     
  161.     OSStatus osStatus = noErr;
  162.     if (m_mpTaskID && (::MPCurrentTaskID() != m_mpTaskID))
  163.     {
  164.     // xxxbobclark The windows implementation of HXThread doesn't
  165.     // shoot the thread in the head, like ::MPTerminateTask() does...
  166.     // it just waits for it to end.
  167.     
  168.     // There is conflicting advice in Apple documentation on how advisable
  169.     // it is to call MPTerminateTask. Listing 3-3 Terminating Tasks, at
  170.     // http://developer.apple.com/techpubs/macosx/Carbon/oss/MultiPServices/Multitasking_MultiproServ/Concepts/MP.1b.html
  171.     // is pretty clear: "When you want to terminate a task, you should call
  172.     // the function MPTerminateTask"... but if you follow the link to
  173.     // MPTerminateTask, it says "you should be very careful when calling
  174.     // MPTerminateTask".
  175.     
  176.     // osStatus = ::MPTerminateTask(m_mpTaskID, NULL);
  177.     ::MPWaitOnQueue(m_mpInternalTerminationNotificationQueueID, NULL, NULL, NULL, kDurationForever);
  178.     ::MPDeleteQueue(m_mpInternalTerminationNotificationQueueID);
  179.     m_mpInternalTerminationNotificationQueueID = NULL;
  180.     m_mpTaskID = NULL;
  181.     }
  182.     
  183.     if (m_mpQueueID)
  184.     {
  185. ::MPDeleteQueue(m_mpQueueID);
  186. m_mpQueueID = NULL;
  187.     }
  188.     
  189.     HX_DELETE(m_pQueueMutex);
  190.     
  191.     if (m_pQueuePostSemaphore != kInvalidID)
  192.     {
  193. ::MPDeleteSemaphore(m_pQueuePostSemaphore);
  194. m_pQueuePostSemaphore = kInvalidID;
  195.     }
  196.     
  197.     if (osStatus != noErr) retval = HXR_FAIL;
  198.     
  199.     return retval;
  200. }
  201. HX_RESULT
  202. HXCarbonThread::GetThreadId(UINT32& ulThreadId)
  203. {
  204.     HX_RESULT retval = HXR_OK;
  205.     
  206.     ulThreadId = (UINT32) m_mpTaskID;
  207.     return retval;
  208. }
  209. ULONG32
  210. HXCarbonThread::GetCurrentThreadID()
  211. {
  212.     MPTaskID id = ::MPCurrentTaskID();
  213.     return (ULONG32) id;
  214. }
  215. HX_RESULT
  216. HXCarbonThread::PostMessage(HXThreadMessage* pMsg, void* pWindowHandle)
  217. {
  218.     HX_RESULT retval = HXR_OK;
  219.     
  220.     HX_ASSERT(pMsg);
  221.     if (!pMsg) return HXR_FAIL;
  222.     
  223.     HX_ASSERT(m_mpQueueID != NULL);
  224.     
  225.     m_pQueueMutex->Lock();
  226.     OSStatus osStatus = ::MPNotifyQueue(m_mpQueueID, (void*)pMsg->m_ulMessage,
  227. (void*)pMsg->m_pParam1, (void*)pMsg->m_pParam2);
  228.     ::MPSignalSemaphore(m_pQueuePostSemaphore);
  229.     m_pQueueMutex->Unlock();
  230.     
  231.     if (osStatus != noErr)
  232.     {
  233. retval = HXR_FAIL;
  234.     }
  235.     
  236.     return retval;
  237. }
  238. HX_RESULT
  239. HXCarbonThread::GetMessage(HXThreadMessage* pMsg, UINT32 ulMsgFilterMix, UINT32 ulMsgFilterMax)
  240. {
  241.     HX_RESULT retval = HXR_OK;
  242.     
  243.     HX_ASSERT(m_mpQueueID != NULL);
  244.     HX_ASSERT(pMsg);
  245.     if (!pMsg) return HXR_FAIL;
  246.     
  247.     void* param1;
  248.     void* param2;
  249.     void* param3;
  250.     
  251.     OSStatus osStatus = ::MPWaitOnSemaphore(m_pQueuePostSemaphore, kDurationForever);
  252.     
  253.     if (osStatus == noErr)
  254.     {
  255. m_pQueueMutex->Lock();
  256. osStatus = ::MPWaitOnQueue(m_mpQueueID, &param1, &param2, &param3, kDurationImmediate);
  257. HX_ASSERT(osStatus == noErr);
  258. m_pQueueMutex->Unlock();
  259.     }
  260.     
  261.     if (osStatus == noErr)
  262.     {
  263. pMsg->m_ulMessage = (UINT32)param1;
  264. pMsg->m_pParam1 = param2; // xxxbobclark I know, I know, this is crazy.
  265. pMsg->m_pParam2 = param3;
  266.     }
  267.     else
  268.     {
  269. retval = HXR_FAIL;
  270.     }
  271.     
  272.     return retval;
  273. }
  274. HX_RESULT
  275. HXCarbonThread::PeekMessage(HXThreadMessage* pMsg, UINT32 ulMsgFilterMix, UINT32 ulMsgFilterMax, BOOL bRemoveMessage)
  276. {
  277.     // xxxbobclark OK so PeekMessage is going to grab the first message (if it exists)
  278.     // and dupe it and replace it in the queue. It will eventually be more complicated
  279.     // than this I think. I think I'll need to mutex-protect this routine and do some
  280.     // wacky stuff to ensure that the queue is in the same order when it exits as it
  281.     // is when it enters.
  282.     
  283.     HX_ASSERT(m_mpQueueID != NULL);
  284.     HX_RESULT retval = HXR_OK;
  285.     
  286.     HX_ASSERT(pMsg);
  287.     if (!pMsg) return HXR_FAIL;
  288.     
  289.     void* param1;
  290.     void* param2;
  291.     void* param3;
  292.     
  293.     m_pQueueMutex->Lock();
  294.     OSStatus osStatus = ::MPWaitOnQueue(m_mpQueueID, &param1, &param2, &param3, kDurationImmediate);
  295.     m_pQueueMutex->Unlock();
  296.     
  297.     if (osStatus == noErr)
  298.     {
  299. pMsg->m_ulMessage = (UINT32)param1;
  300. pMsg->m_pParam1 = param2;
  301. pMsg->m_pParam2 = param3;
  302. if (!bRemoveMessage)
  303. {
  304.     // replace it in the queue. !!!xxxbobclark but this is
  305.     // in the wrong place!!!
  306.     HX_ASSERT(!"THIS IS NOT FINISHED! THE QUEUE IS BEING RESTORED INCORRECTLY!");
  307.     PostMessage(pMsg, NULL);
  308. }
  309.     }
  310.     else
  311.     {
  312. pMsg->m_ulMessage = 0;
  313. retval = HXR_FAIL; // no event to get!
  314.     }
  315.     
  316.     return retval;
  317. }
  318. HX_RESULT
  319. HXCarbonThread::PeekMessageMatching( HXThreadMessage* pMsg,
  320.                                       HXThreadMessage* pMatch,
  321.                                       BOOL bRemoveMessage )
  322. {
  323.     // we're going to create a temp queue, copy each message from the main queue into it until we find
  324.     // a matching message, then copy the rest
  325.     HX_ASSERT(m_mpQueueID != kInvalidID);
  326.     HX_RESULT retval = HXR_OK;
  327.     
  328.     HX_ASSERT(pMsg);
  329.     if (!pMsg) return HXR_FAIL;
  330.     
  331.     HX_ASSERT(pMatch);
  332.     if (!pMatch) return HXR_FAIL;
  333.     
  334.     void* param1;
  335.     void* param2;
  336.     void* param3;
  337.     
  338.     OSStatus osResult;
  339.     
  340.     m_pQueueMutex->Lock();
  341.     // create a temp queue, all messages will be copied into this queue 
  342.     // (except matching message if bRemoveMessage == TRUE)
  343.     MPQueueID tempQ;
  344.     osResult = ::MPCreateQueue(&tempQ);
  345.     HX_ASSERT(tempQ != kInvalidID);
  346.     BOOL foundAMatch = FALSE;
  347.     
  348.     const BOOL bSkipMessage  = (pMatch->m_ulMessage == 0);
  349.     const BOOL bSkipParam1   = (pMatch->m_pParam1 == NULL);
  350.     const BOOL bSkipParam2   = (pMatch->m_pParam2 == NULL);
  351.     while((osResult = ::MPWaitOnQueue(m_mpQueueID, &param1, &param2, &param3, kDurationImmediate)) == noErr)
  352.     {        
  353.         // does it match?
  354.         if( ( bSkipMessage || pMatch->m_ulMessage == (UINT32) param1 ) &&
  355.             ( bSkipParam1  || pMatch->m_pParam1 == param2 ) &&
  356.             ( bSkipParam2  || pMatch->m_pParam2 == param3 ) )
  357.         {
  358.             foundAMatch = TRUE;
  359.             break;
  360.         }
  361.         
  362.         // copy it into the temp queue
  363.         ::MPNotifyQueue(tempQ, param1, param2, param3);
  364.     }
  365.     
  366.     if( foundAMatch )
  367.     {
  368. // copy the found message to the out variable
  369. pMsg->m_ulMessage = (UINT32)param1;
  370. pMsg->m_pParam1 = param2;
  371. pMsg->m_pParam2 = param3;
  372. // if we aren't supposed to remove it, re-post it
  373. if( !bRemoveMessage )
  374. {
  375.     ::MPNotifyQueue(tempQ, param1, param2, param3);
  376. }
  377. // now copy any remaining messages
  378.         while((osResult = ::MPWaitOnQueue(m_mpQueueID, &param1, &param2, &param3, kDurationImmediate)) == noErr)
  379.         {
  380.             ::MPNotifyQueue(tempQ, param1, param2, param3);
  381.         }
  382.         
  383.         retval = HXR_OK;
  384.     }
  385.     else
  386.     {
  387.         pMsg->m_ulMessage = 0;
  388.         retval = HXR_FAIL;
  389.     }
  390.     
  391.     // now that the original queue is empty, throw it away and keep the copy that we made
  392.     ::MPDeleteQueue(m_mpQueueID);
  393.     m_mpQueueID = tempQ;
  394.     m_pQueueMutex->Unlock();
  395.     return retval;
  396. }
  397. HX_RESULT
  398. HXCarbonThread::DispatchMessage(HXThreadMessage* pMsg)
  399. {
  400.     HX_RESULT retval = HXR_NOTIMPL;
  401.     HX_ASSERT(!"Unimplemented DispatchMessage!");
  402.     return retval;
  403. }
  404. // HXCarbonEvent
  405. HXCarbonEvent::HXCarbonEvent(const char* pEventName, BOOL bManualReset)
  406.   : m_mpSemaphoreID(NULL)
  407.   , m_IsManuallyReset( bManualReset )
  408. {
  409.     MPSemaphoreCount semaphoreMax = bManualReset ? INT_MAX : 1;
  410.     OSStatus osStatus = ::MPCreateSemaphore(semaphoreMax, 0, &m_mpSemaphoreID);
  411.     HX_ASSERT(osStatus == noErr);
  412. }
  413. HXCarbonEvent::~HXCarbonEvent()
  414. {
  415.     OSStatus osStatus = ::MPDeleteSemaphore(m_mpSemaphoreID);
  416.     m_mpSemaphoreID = NULL;
  417.     HX_ASSERT(osStatus == noErr);
  418. }
  419. HX_RESULT
  420. HXCarbonEvent::SignalEvent(void)
  421. {
  422.     HX_RESULT retval = HXR_OK;
  423.     OSStatus osStatus = ::MPSignalSemaphore(m_mpSemaphoreID);
  424.     if (osStatus != noErr && osStatus != kMPInsufficientResourcesErr) retval = HXR_FAIL;
  425.     
  426.     return retval;
  427. }
  428. HX_RESULT
  429. HXCarbonEvent::ResetEvent(void)
  430. {
  431.     HX_RESULT retval = HXR_OK;
  432.     OSStatus osStatus;
  433.     
  434.     while(noErr == (osStatus = ::MPWaitOnSemaphore(m_mpSemaphoreID, kDurationImmediate)))
  435.     {
  436.     }
  437.     
  438.     return retval;
  439. }
  440. void*
  441. HXCarbonEvent::GetEventHandle(void)
  442. {
  443.     return (void*)m_mpSemaphoreID;
  444. }
  445. HX_RESULT
  446. HXCarbonEvent::Wait(UINT32 uTimeoutPeriod)
  447. {
  448.     HX_RESULT retval = HXR_OK;
  449.     
  450.     Duration timeout = ( uTimeoutPeriod == ALLFS ) ? kDurationForever : ( uTimeoutPeriod * kDurationMillisecond );
  451.     
  452.     OSStatus osStatus = ::MPWaitOnSemaphore(m_mpSemaphoreID, timeout);
  453.     
  454.     switch (osStatus)
  455.     {
  456. case noErr:
  457.     if( m_IsManuallyReset )
  458.     {
  459.      // needs to go back into the raised state until Reset is explicitly called
  460.      ::MPSignalSemaphore(m_mpSemaphoreID);
  461.     }
  462.     retval = HXR_OK;
  463.     break;
  464. case kMPTimeoutErr:
  465.     retval = HXR_WOULD_BLOCK; // winthrd.cpp returns this if the wait times out
  466.     break;
  467. default:
  468.     retval = HXR_FAIL;
  469.     break;
  470.     }
  471.     
  472.     return retval;
  473. }
  474. // HXCarbonManualEvent
  475. HXCarbonManualEvent::HXCarbonManualEvent(const char* pEventName)
  476.  : m_pMutex(NULL)
  477.  , m_bIsSignalled(FALSE)
  478.  , m_InternalSemaphoreID(NULL)
  479. {
  480.     HXMutex::MakeMutex(m_pMutex);
  481.     OSStatus osStatus = ::MPCreateSemaphore(1, 0, &m_InternalSemaphoreID);
  482. }
  483. HXCarbonManualEvent::~HXCarbonManualEvent()
  484. {
  485.     OSStatus osStatus = ::MPDeleteSemaphore(m_InternalSemaphoreID);
  486.     m_InternalSemaphoreID = NULL;
  487.     HX_DELETE(m_pMutex);
  488. }
  489. HX_RESULT
  490. HXCarbonManualEvent::SignalEvent()
  491. {
  492.     m_pMutex->Lock();
  493.     m_bIsSignalled = TRUE;
  494.     ::MPSignalSemaphore(m_InternalSemaphoreID); // in case we're waiting.
  495.     m_pMutex->Unlock();
  496.     
  497.     return HXR_OK;
  498. }
  499. HX_RESULT
  500. HXCarbonManualEvent::ResetEvent()
  501. {
  502.     m_pMutex->Lock();
  503.     m_bIsSignalled = FALSE;
  504.     ::MPWaitOnSemaphore(m_InternalSemaphoreID, kDurationImmediate); // just clear it out...
  505.     m_pMutex->Unlock();
  506.     return HXR_OK;
  507. }
  508. HX_RESULT
  509. HXCarbonManualEvent::Wait(UINT32 uTimeoutPeriod)
  510. {
  511.     BOOL bDone = FALSE;
  512.     
  513.     HX_RESULT retVal = HXR_OK;
  514.     
  515.     while (!bDone)
  516.     {
  517. m_pMutex->Lock();
  518. BOOL bIsSignalled = m_bIsSignalled;
  519. m_pMutex->Unlock();
  520. if (bIsSignalled)
  521. {
  522.     bDone = TRUE;
  523. }
  524. else
  525. {
  526.     // xxxbobclark rely on MP semaphore
  527.     
  528.     Duration timeout = ( uTimeoutPeriod == ALLFS ) ? kDurationForever : ( uTimeoutPeriod * kDurationMillisecond );
  529.     
  530.     OSStatus osStatus = ::MPWaitOnSemaphore(m_InternalSemaphoreID, timeout);
  531.     bDone = TRUE;
  532.     if (osStatus == kMPTimeoutErr)
  533.     {
  534. retVal = HXR_WOULD_BLOCK;
  535.     }
  536. }
  537.     }
  538.     return retVal;
  539. }
  540. void*
  541. HXCarbonManualEvent::GetEventHandle (void)
  542. {
  543.     return (void*)this;
  544. }
  545. // HXCarbonMutex
  546. HXCarbonMutex::HXCarbonMutex()
  547. {
  548.     MPCreateCriticalRegion(&mCriticalRegion);
  549. }
  550. HXCarbonMutex::~HXCarbonMutex()
  551. {
  552.     MPDeleteCriticalRegion(mCriticalRegion);
  553. }
  554. HX_RESULT
  555. HXCarbonMutex::Lock(void)
  556. {
  557.     MPEnterCriticalRegion(mCriticalRegion, kDurationForever);
  558.     return HXR_OK;
  559. }
  560. HX_RESULT
  561. HXCarbonMutex::Unlock(void)
  562. {
  563.     MPExitCriticalRegion(mCriticalRegion);
  564.     return HXR_OK;
  565. }
  566. HX_RESULT
  567. HXCarbonMutex::Trylock(void)
  568. {
  569.     HX_RESULT retval = HXR_OK;
  570.     OSStatus osStatus = MPEnterCriticalRegion(mCriticalRegion, kDurationImmediate);
  571.     
  572.     if (osStatus != noErr)
  573.     {
  574.      retval = HXR_FAIL;
  575.     } 
  576.     return retval;
  577. }
  578. //HXCarbonSemaphore
  579. HXCarbonSemaphore::HXCarbonSemaphore( UINT32 unInitialCount /*=0*/)
  580. :m_mpSemaphoreID(0)
  581. {
  582.    OSStatus osStatus = ::MPCreateSemaphore(INT_MAX, unInitialCount, &m_mpSemaphoreID);
  583.    
  584.    HX_ASSERT(osStatus == noErr);
  585. }
  586. HXCarbonSemaphore::~HXCarbonSemaphore()
  587. {
  588. MPDeleteSemaphore(m_mpSemaphoreID);
  589. }
  590. HX_RESULT HXCarbonSemaphore::Post()
  591. {
  592. HX_RESULT retval = HXR_OK;
  593. OSStatus osStatus = MPSignalSemaphore(m_mpSemaphoreID);
  594. if (osStatus != noErr)
  595. {
  596. retval = HXR_FAIL;
  597. }
  598. return retval; 
  599. }
  600. HX_RESULT HXCarbonSemaphore::Wait()
  601. {
  602. HX_RESULT retval = HXR_OK;
  603. OSStatus osStatus = MPWaitOnSemaphore(m_mpSemaphoreID, kDurationForever);
  604. if (osStatus != noErr)
  605. {
  606. retval = HXR_FAIL;
  607. }
  608.     
  609. return retval;
  610. }
  611. HX_RESULT HXCarbonSemaphore::TryWait()
  612. {
  613. HX_RESULT retval = HXR_OK;
  614. OSStatus osStatus = MPWaitOnSemaphore(m_mpSemaphoreID, kDurationImmediate);
  615. if (osStatus != noErr)
  616. {
  617. retval = HXR_FAIL;
  618. }
  619. return retval;
  620. }
  621. #if 0
  622. // HXCarbonAsyncTimer
  623. HXCarbonAsyncTimer::HXCarbonAsyncTimer(ULONG32 ulTimeOut, HXThread* pReceivingThread)
  624.  : m_ulTimeout(ulTimeOut)
  625.  , m_pReceivingThread(pReceivingThread)
  626.  , m_CarbonTimerUPP(NULL)
  627.  , m_CarbonTimerRef(NULL)
  628.  , m_msg(NULL)
  629. {
  630.     m_msg = new HXThreadMessage(HXMSG_ASYNC_TIMER, (void*)m_ulTimeout, NULL, NULL);
  631.     m_CarbonTimerUPP = ::NewEventLoopTimerUPP((EventLoopTimerProcPtr)MyCarbonTimer);
  632.     ::InstallEventLoopTimer(GetCurrentEventLoop(), 0, kEventDurationMillisecond *
  633. m_ulTimeout, m_CarbonTimerUPP, this, &m_CarbonTimerRef);
  634. }
  635. HXCarbonAsyncTimer::~HXCarbonAsyncTimer()
  636. {
  637.     if (m_CarbonTimerRef)
  638.     {
  639. ::RemoveEventLoopTimer(m_CarbonTimerRef);
  640. m_CarbonTimerRef = NULL;
  641.     }
  642.     if (m_CarbonTimerUPP)
  643.     {
  644. ::DisposeEventLoopTimerUPP(m_CarbonTimerUPP);
  645. m_CarbonTimerUPP = NULL;
  646.     }
  647.     delete m_msg;
  648. }
  649. /* static */
  650. UINT32
  651. HXCarbonAsyncTimer::SetTimer(ULONG32 ulTimeOut, HXThread* pReceivingThread)
  652. {
  653.     volatile HXCarbonAsyncTimer* pAsyncTimer = new HXCarbonAsyncTimer(ulTimeOut, pReceivingThread);
  654.     return (UINT32) pAsyncTimer;
  655. }
  656. /* static */
  657. void
  658. HXCarbonAsyncTimer::MyCarbonTimer(EventLoopTimerRef, HXCarbonAsyncTimer* pAsyncTimer)
  659. {
  660.     HX_ASSERT(pAsyncTimer);
  661.     HX_ASSERT(pAsyncTimer->m_pReceivingThread);
  662.     HXThreadMessage theMsg(HXMSG_ASYNC_TIMER, (void*)pAsyncTimer->m_ulTimeout, NULL, NULL);
  663.     pAsyncTimer->m_pReceivingThread->PostMessage(&theMsg);
  664. }
  665. #endif
  666. #endif