CVS update: /common/system/platform/mac/, /common/system/pub/platform/mac/
bobclark at helixcommunity.org bobclark at helixcommunity.orgUser: bobclark Date: 03/01/24 18:29:03 Modified /common/system/platform/mac/ carbthrd.cpp /common/system/pub/platform/mac/ carbthrd.h Log adding manual events and other enhancements to carbon synchronization classes File Changes: Directory: /common/system/platform/mac/ ======================================= File [changed]: carbthrd.cpp Url: https://common.helixcommunity.org/source/browse/common/system/platform/mac/carbthrd.cpp.diff?r1=1.2&r2=1.3 Delta lines: +195 -2 --------------------- --- carbthrd.cpp 18 Nov 2002 21:02:56 -0000 1.2 +++ carbthrd.cpp 25 Jan 2003 02:29:03 -0000 1.3 @@ -41,6 +41,8 @@ HXCarbonThread::HXCarbonThread() : m_mpTaskID(NULL) , m_mpQueueID(NULL) + , m_pQueueMutex(NULL) + , m_pQueuePostSemaphore(kInvalidID) , m_mpInternalTerminationNotificationQueueID(NULL) { // xxxbobclark there's a kludgey main app thread wrapper thingie @@ -48,8 +50,9 @@ // HXCarbonThread gets used without HXCarbonThread::CreateThread() // being called... but it requires m_mpQueueID. So we create it in // the ctor. + HXMutex::MakeMutex(m_pQueueMutex); + ::MPCreateSemaphore(INT_MAX, 0, &m_pQueuePostSemaphore); OSStatus osResult = MPCreateQueue(&m_mpQueueID); - } HXCarbonThread::~HXCarbonThread() @@ -59,6 +62,8 @@ // xxxbobclark should I remove the queue here if it exists? HX_ASSERT(m_mpQueueID == NULL); HX_ASSERT(m_mpTaskID == NULL); + HX_ASSERT(m_pQueueMutex == NULL); + HX_ASSERT(m_pQueuePostSemaphore == kInvalidID); } HX_RESULT @@ -180,6 +185,14 @@ m_mpQueueID = NULL; } + HX_DELETE(m_pQueueMutex); + + if (m_pQueuePostSemaphore != kInvalidID) + { + ::MPDeleteSemaphore(m_pQueuePostSemaphore); + m_pQueuePostSemaphore = kInvalidID; + } + if (osStatus != noErr) retval = HXR_FAIL; return retval; @@ -212,8 +225,11 @@ HX_ASSERT(m_mpQueueID != NULL); + m_pQueueMutex->Lock(); OSStatus osStatus = ::MPNotifyQueue(m_mpQueueID, (void*)pMsg->m_ulMessage, (void*)pMsg->m_pParam1, (void*)pMsg->m_pParam2); + ::MPSignalSemaphore(m_pQueuePostSemaphore); + m_pQueueMutex->Unlock(); if (osStatus != noErr) { @@ -236,7 +252,15 @@ void* param2; void* param3; - OSStatus osStatus = ::MPWaitOnQueue(m_mpQueueID, ¶m1, ¶m2, ¶m3, kDurationForever); + OSStatus osStatus = ::MPWaitOnSemaphore(m_pQueuePostSemaphore, kDurationForever); + + if (osStatus == noErr) + { + m_pQueueMutex->Lock(); + osStatus = ::MPWaitOnQueue(m_mpQueueID, ¶m1, ¶m2, ¶m3, kDurationImmediate); + HX_ASSERT(osStatus == noErr); + m_pQueueMutex->Unlock(); + } if (osStatus == noErr) { @@ -271,7 +295,9 @@ void* param2; void* param3; + m_pQueueMutex->Lock(); OSStatus osStatus = ::MPWaitOnQueue(m_mpQueueID, ¶m1, ¶m2, ¶m3, kDurationImmediate); + m_pQueueMutex->Unlock(); if (osStatus == noErr) { @@ -298,6 +324,93 @@ } HX_RESULT +HXCarbonThread::PeekMessageMatching( HXThreadMessage* pMsg, + HXThreadMessage* pMatch, + BOOL bRemoveMessage ) +{ + // we're going to create a temp queue, copy each message from the main queue into it until we find + // a matching message, then copy the rest + + HX_ASSERT(m_mpQueueID != kInvalidID); + HX_RESULT retval = HXR_OK; + + HX_ASSERT(pMsg); + if (!pMsg) return HXR_FAIL; + + HX_ASSERT(pMatch); + if (!pMatch) return HXR_FAIL; + + void* param1; + void* param2; + void* param3; + + OSStatus osResult; + + m_pQueueMutex->Lock(); + + // create a temp queue, all messages will be copied into this queue + // (except matching message if bRemoveMessage == TRUE) + MPQueueID tempQ; + osResult = ::MPCreateQueue(&tempQ); + HX_ASSERT(tempQ != kInvalidID); + + BOOL foundAMatch = FALSE; + + const BOOL bSkipMessage = (pMatch->m_ulMessage == 0); + const BOOL bSkipParam1 = (pMatch->m_pParam1 == NULL); + const BOOL bSkipParam2 = (pMatch->m_pParam2 == NULL); + while((osResult = ::MPWaitOnQueue(m_mpQueueID, ¶m1, ¶m2, ¶m3, kDurationImmediate)) == noErr) + { + // does it match? + if( ( bSkipMessage || pMatch->m_ulMessage == (UINT32) param1 ) && + ( bSkipParam1 || pMatch->m_pParam1 == param2 ) && + ( bSkipParam2 || pMatch->m_pParam2 == param3 ) ) + { + foundAMatch = TRUE; + break; + } + + // copy it into the temp queue + ::MPNotifyQueue(tempQ, param1, param2, param3); + } + + if( foundAMatch ) + { + // copy the found message to the out variable + pMsg->m_ulMessage = (UINT32)param1; + pMsg->m_pParam1 = param2; + pMsg->m_pParam2 = param3; + + // if we aren't supposed to remove it, re-post it + if( !bRemoveMessage ) + { + ::MPNotifyQueue(tempQ, param1, param2, param3); + } + + // now copy any remaining messages + while((osResult = ::MPWaitOnQueue(m_mpQueueID, ¶m1, ¶m2, ¶m3, kDurationImmediate)) == noErr) + { + ::MPNotifyQueue(tempQ, param1, param2, param3); + } + + retval = HXR_OK; + } + else + { + pMsg->m_ulMessage = 0; + retval = HXR_FAIL; + } + + // now that the original queue is empty, throw it away and keep the copy that we made + ::MPDeleteQueue(m_mpQueueID); + m_mpQueueID = tempQ; + + m_pQueueMutex->Unlock(); + + return retval; +} + +HX_RESULT HXCarbonThread::DispatchMessage(HXThreadMessage* pMsg) { HX_RESULT retval = HXR_NOTIMPL; @@ -385,6 +498,86 @@ return retval; } + +// HXCarbonManualEvent + +HXCarbonManualEvent::HXCarbonManualEvent(const char* pEventName) + : m_pMutex(NULL) + , m_bIsSignalled(FALSE) + , m_InternalSemaphoreID(NULL) +{ + HXMutex::MakeMutex(m_pMutex); + OSStatus osStatus = ::MPCreateSemaphore(1, 0, &m_InternalSemaphoreID); +} + +HXCarbonManualEvent::~HXCarbonManualEvent() +{ + OSStatus osStatus = ::MPDeleteSemaphore(m_InternalSemaphoreID); + m_InternalSemaphoreID = NULL; + HX_DELETE(m_pMutex); +} + +HX_RESULT +HXCarbonManualEvent::SignalEvent() +{ + m_pMutex->Lock(); + m_bIsSignalled = TRUE; + ::MPSignalSemaphore(m_InternalSemaphoreID); // in case we're waiting. + m_pMutex->Unlock(); + + return HXR_OK; +} + +HX_RESULT +HXCarbonManualEvent::ResetEvent() +{ + m_pMutex->Lock(); + m_bIsSignalled = FALSE; + ::MPWaitOnSemaphore(m_InternalSemaphoreID, kDurationImmediate); // just clear it out... + m_pMutex->Unlock(); + return HXR_OK; +} + +HX_RESULT +HXCarbonManualEvent::Wait(UINT32 uTimeoutPeriod) +{ + BOOL bDone = FALSE; + + HX_RESULT retVal = HXR_OK; + + while (!bDone) + { + m_pMutex->Lock(); + BOOL bIsSignalled = m_bIsSignalled; + m_pMutex->Unlock(); + if (bIsSignalled) + { + bDone = TRUE; + } + else + { + // xxxbobclark rely on MP semaphore + + Duration timeout = ( uTimeoutPeriod == ALLFS ) ? kDurationForever : ( uTimeoutPeriod * kDurationMillisecond ); + + OSStatus osStatus = ::MPWaitOnSemaphore(m_InternalSemaphoreID, timeout); + bDone = TRUE; + if (osStatus == kMPTimeoutErr) + { + retVal = HXR_WOULD_BLOCK; + } + } + } + + return retVal; +} + +void* +HXCarbonManualEvent::GetEventHandle (void) +{ + return (void*)this; +} + // HXCarbonMutex Directory: /common/system/pub/platform/mac/ =========================================== File [changed]: carbthrd.h Url: https://common.helixcommunity.org/source/browse/common/system/pub/platform/mac/carbthrd.h.diff?r1=1.2&r2=1.3 Delta lines: +23 -5 -------------------- --- carbthrd.h 18 Nov 2002 21:02:56 -0000 1.2 +++ carbthrd.h 25 Jan 2003 02:29:03 -0000 1.3 @@ -41,11 +41,6 @@ #ifndef _HX_CARBON_THREAD #define _HX_CARBON_THREAD -// NOTE WELL: Mac Threads are cooperative and not interrupt-safe. -// So be sure each thread calls YieldTimeSlice to allow other threads -// to run, and do not call any of the yielding or blocking methods -// (YieldTimeSlice, Lock, Wait, GetMessage) at interrupt or deferred-task time. - class HXCarbonThread : public HXThread { public: @@ -79,10 +74,14 @@ virtual HX_RESULT PeekMessage(HXThreadMessage* pMsg, UINT32 ulMsgFilterMix = 0, UINT32 ulMsgFilterMax = 0, BOOL bRemoveMessage = TRUE); + virtual HX_RESULT PeekMessageMatching(HXThreadMessage* pMsg, HXThreadMessage* pMatch, BOOL bRemoveMessage); + virtual HX_RESULT DispatchMessage(HXThreadMessage* pMsg); private: + HXMutex* m_pQueueMutex; + MPSemaphoreID m_pQueuePostSemaphore; MPTaskID m_mpTaskID; MPQueueID m_mpQueueID; MPQueueID m_mpInternalTerminationNotificationQueueID; @@ -106,6 +105,25 @@ MPSemaphoreID m_mpSemaphoreID; BOOL m_IsManuallyReset; +}; + +class HXCarbonManualEvent : public HXEvent +{ +public: + + HXCarbonManualEvent(const char* pEventName = NULL); + virtual ~HXCarbonManualEvent(void); + + virtual HX_RESULT SignalEvent (void); + virtual HX_RESULT ResetEvent (void); + virtual void* GetEventHandle (void); + virtual HX_RESULT Wait (UINT32 uTimeoutPeriod = ALLFS); + +private: + + HXMutex* m_pMutex; + BOOL m_bIsSignalled; + MPSemaphoreID m_InternalSemaphoreID; }; class HXCarbonMutex : public HXMutex --------------------------------------------------------------------- To unsubscribe, e-mail: cvs-unsubscribe at common.helixcommunity.org For additional commands, e-mail: cvs-help at common.helixcommunity.org