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

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