public static void SatisfyWaitForAll( ThreadWaitInfo waitInfo, WaitableObject[] waitedObjects, int waitedCount, int signaledWaitedObjectIndex) { Debug.Assert(waitInfo != null); Debug.Assert(waitInfo.Thread != RuntimeThread.CurrentThread); Debug.Assert(waitedObjects != null); Debug.Assert(waitedObjects.Length >= waitedCount); Debug.Assert(waitedCount > 1); Debug.Assert(signaledWaitedObjectIndex >= 0); Debug.Assert(signaledWaitedObjectIndex <= WaitHandle.MaxWaitHandles); for (int i = 0; i < waitedCount; ++i) { Debug.Assert(waitedObjects[i] != null); if (i == signaledWaitedObjectIndex) { continue; } WaitableObject waitedObject = waitedObjects[i]; if (waitedObject.IsSignaled) { waitedObject.AcceptSignal(waitInfo); continue; } Debug.Assert(waitedObject.IsMutex); OwnershipInfo ownershipInfo = waitedObject._ownershipInfo; Debug.Assert(ownershipInfo.Thread == waitInfo.Thread); ownershipInfo.IncrementReacquireCount(); } }
public static int Wait( WaitableObject[] waitableObjects, int count, bool waitForAll, ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize, WaitHandle[] waitHandlesForAbandon) { s_lock.VerifyIsNotLocked(); Debug.Assert(waitInfo != null); Debug.Assert(waitInfo.Thread == RuntimeThread.CurrentThread); Debug.Assert(waitableObjects != null); Debug.Assert(waitableObjects.Length >= count); Debug.Assert(count > 1); Debug.Assert(timeoutMilliseconds >= -1); bool needToWait = false; s_lock.Acquire(); try { if (interruptible && waitInfo.CheckAndResetPendingInterrupt) { throw new ThreadInterruptedException(); } if (!waitForAll) { // Check if any is already signaled for (int i = 0; i < count; ++i) { WaitableObject waitableObject = waitableObjects[i]; Debug.Assert(waitableObject != null); if (waitableObject.IsSignaled) { bool isAbandoned = waitableObject.IsAbandonedMutex; waitableObject.AcceptSignal(waitInfo); if (isAbandoned) { if (waitHandlesForAbandon == null) { throw new AbandonedMutexException(); } else { throw new AbandonedMutexException(i, waitHandlesForAbandon[i]); } } return(i); } if (waitableObject.IsMutex) { OwnershipInfo ownershipInfo = waitableObject._ownershipInfo; if (ownershipInfo.Thread == waitInfo.Thread) { if (!ownershipInfo.CanIncrementReacquireCount) { throw new OverflowException(SR.Overflow_MutexReacquireCount); } ownershipInfo.IncrementReacquireCount(); return(i); } } } } else { // Check if all are already signaled bool areAllSignaled = true; bool isAnyAbandonedMutex = false; for (int i = 0; i < count; ++i) { WaitableObject waitableObject = waitableObjects[i]; Debug.Assert(waitableObject != null); if (waitableObject.IsSignaled) { if (!isAnyAbandonedMutex && waitableObject.IsAbandonedMutex) { isAnyAbandonedMutex = true; } continue; } if (waitableObject.IsMutex) { OwnershipInfo ownershipInfo = waitableObject._ownershipInfo; if (ownershipInfo.Thread == waitInfo.Thread) { if (!ownershipInfo.CanIncrementReacquireCount) { throw new OverflowException(SR.Overflow_MutexReacquireCount); } continue; } } areAllSignaled = false; break; } if (areAllSignaled) { for (int i = 0; i < count; ++i) { WaitableObject waitableObject = waitableObjects[i]; if (waitableObject.IsSignaled) { waitableObject.AcceptSignal(waitInfo); continue; } Debug.Assert(waitableObject.IsMutex); OwnershipInfo ownershipInfo = waitableObject._ownershipInfo; Debug.Assert(ownershipInfo.Thread == waitInfo.Thread); ownershipInfo.IncrementReacquireCount(); } if (isAnyAbandonedMutex) { throw new AbandonedMutexException(); } return(0); } } if (timeoutMilliseconds == 0) { return(WaitHandle.WaitTimeout); } waitableObjects = null; // no need to clear this anymore, RegisterWait / Wait will take over from here waitInfo.RegisterWait(count, prioritize, waitForAll); needToWait = true; } finally { if (waitableObjects != null) { for (int i = 0; i < count; ++i) { waitableObjects[i] = null; } } // Once the wait function is called, it will release the lock if (!needToWait) { s_lock.Release(); } } return(waitInfo.Wait(timeoutMilliseconds, interruptible, waitHandlesForAbandon, isSleep: false)); }
public static int Wait( WaitableObject?[]?waitableObjects, int count, bool waitForAll, ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize) { s_lock.VerifyIsNotLocked(); Debug.Assert(waitInfo != null); Debug.Assert(waitInfo.Thread == Thread.CurrentThread); Debug.Assert(waitableObjects != null); Debug.Assert(waitableObjects.Length >= count); Debug.Assert(count > 1); Debug.Assert(timeoutMilliseconds >= -1); var lockHolder = new LockHolder(s_lock); try { if (interruptible && waitInfo.CheckAndResetPendingInterrupt) { lockHolder.Dispose(); throw new ThreadInterruptedException(); } if (!waitForAll) { // Check if any is already signaled for (int i = 0; i < count; ++i) { WaitableObject waitableObject = waitableObjects[i] !; Debug.Assert(waitableObject != null); if (waitableObject.IsSignaled) { bool isAbandoned = waitableObject.IsAbandonedMutex; waitableObject.AcceptSignal(waitInfo); if (isAbandoned) { return(WaitHandle.WaitAbandoned + i); } return(WaitHandle.WaitSuccess + i); } if (waitableObject.IsMutex) { OwnershipInfo ownershipInfo = waitableObject._ownershipInfo !; if (ownershipInfo.Thread == waitInfo.Thread) { if (!ownershipInfo.CanIncrementReacquireCount) { lockHolder.Dispose(); throw new OverflowException(SR.Overflow_MutexReacquireCount); } ownershipInfo.IncrementReacquireCount(); return(WaitHandle.WaitSuccess + i); } } } } else { // Check if all are already signaled bool areAllSignaled = true; bool isAnyAbandonedMutex = false; for (int i = 0; i < count; ++i) { WaitableObject waitableObject = waitableObjects[i] !; Debug.Assert(waitableObject != null); if (waitableObject.IsSignaled) { if (!isAnyAbandonedMutex && waitableObject.IsAbandonedMutex) { isAnyAbandonedMutex = true; } continue; } if (waitableObject.IsMutex) { OwnershipInfo ownershipInfo = waitableObject._ownershipInfo !; if (ownershipInfo.Thread == waitInfo.Thread) { if (!ownershipInfo.CanIncrementReacquireCount) { lockHolder.Dispose(); throw new OverflowException(SR.Overflow_MutexReacquireCount); } continue; } } areAllSignaled = false; break; } if (areAllSignaled) { for (int i = 0; i < count; ++i) { WaitableObject waitableObject = waitableObjects[i] !; if (waitableObject.IsSignaled) { waitableObject.AcceptSignal(waitInfo); continue; } Debug.Assert(waitableObject.IsMutex); OwnershipInfo ownershipInfo = waitableObject._ownershipInfo !; Debug.Assert(ownershipInfo.Thread == waitInfo.Thread); ownershipInfo.IncrementReacquireCount(); } if (isAnyAbandonedMutex) { lockHolder.Dispose(); throw new AbandonedMutexException(); } return(WaitHandle.WaitSuccess); } } if (timeoutMilliseconds == 0) { return(WaitHandle.WaitTimeout); } waitableObjects = null; // no need to clear this anymore, RegisterWait / Wait will take over from here waitInfo.RegisterWait(count, prioritize, waitForAll); return(waitInfo.Wait(timeoutMilliseconds, interruptible, isSleep: false, ref lockHolder)); } finally { lockHolder.Dispose(); if (waitableObjects != null) { for (int i = 0; i < count; ++i) { waitableObjects[i] = null; } } } }