Boolean VNonVirtualCriticalSection::Lock() { VTaskID currentTaskID = VTask::GetCurrentID(); do { VTaskID owner = (VTaskID) VInterlocked::CompareExchange((sLONG*) &fOwner, (sLONG) NULL_TASK_ID, (sLONG) currentTaskID); if (owner == NULL_TASK_ID) { assert(fUseCount == 0); fUseCount = 1; } else if (fOwner == currentTaskID) { ++fUseCount; } else { sLONG unlockCount = sUnlockCount; VSyncEvent* event = VInterlocked::ExchangePtr( &fEvent); if (event != NULL) { event->Retain(); if (VInterlocked::CompareExchangePtr((void **)&fEvent, NULL, event) != NULL) { event->Unlock(); event->Release(); VTask::YieldNow(); } else { while (VInterlocked::CompareExchange(&sUnlockCount, sUnlockCount, sUnlockCount) != sUnlockCount) VTask::YieldNow(); if (sUnlockCount == unlockCount) event->Lock( 100); else VTask::YieldNow(); } event->Release(); } else { event = new VSyncEvent; if (VInterlocked::CompareExchangePtr((void **)&fEvent, NULL, event) != NULL) { event->Unlock(); event->Release(); VTask::YieldNow(); } } } } while(fOwner != currentTaskID); return true; }
Boolean VSmallCriticalSection::Unlock() { //assert((fOwner == (sWORD)VTask::GetCurrentID()) && (fUseCount > 0) && (fUseCount < 32000L)); assert(fUseCount > 0); VSyncEvent* event = NULL; VInterlocked::Increment(&sUnlockCount); // Unlock or another successfull lock can only be called from same thead (so no contention can occur on fUseCount) if (--fUseCount == 0) { // capture currently set event event = VInterlocked::ExchangePtr(&fEvent); VTaskID owner = VInterlocked::Exchange((sLONG*) &fOwner, (sLONG) 0); //assert(owner == VTask::GetCurrentID()); if (event != NULL) { event->Unlock(); event->Release(); } } return true; }
Boolean VSmallCriticalSection::Lock() { sWORD currentTaskID = (sWORD)VTask::GetCurrentID(); LongAsDoubleWord doubleWord; doubleWord.first = (sWORD)currentTaskID; doubleWord.second = 0; do { sLONG owner = VInterlocked::CompareExchange((sLONG*) &fOwner, (sLONG) 0, *((sLONG*) &doubleWord)); if (owner == 0) { assert(fUseCount == 0); fUseCount = 1; } else if (fOwner == currentTaskID) { ++fUseCount; } else { sLONG unlockCount = sUnlockCount; VSyncEvent* event = VInterlocked::ExchangePtr(&fEvent); if (event != NULL) { event->Retain(); if (VInterlocked::CompareExchangePtr((void**)&fEvent, NULL, event) != NULL) { event->Unlock(); VTask::YieldNow(); } else { if (sUnlockCount == unlockCount) event->Lock(100); else VTask::YieldNow(); } event->Release(); } else { event = new VSyncEvent; if (VInterlocked::CompareExchangePtr((void**)&fEvent, NULL, event) != NULL) { event->Release(); VTask::YieldNow(); } } } } while (fOwner != currentTaskID); return true; }
Boolean VNonVirtualCriticalSection::Unlock() { assert((fOwner == VTask::GetCurrentID()) && (fUseCount > 0) && (fUseCount < 32000L)); //assert(fUseCount > 0); VSyncEvent* event = NULL; VInterlocked::Increment(&sUnlockCount); if (--fUseCount == 0) { event = VInterlocked::ExchangePtr(&fEvent); VTaskID owner = VInterlocked::Exchange((sLONG*) &fOwner, (sLONG) NULL_TASK_ID); //assert(owner == VTask::GetCurrentID()); if (event != NULL) { event->Unlock(); event->Release(); } } return true; }