/// <summary> /// This function does not check for a pending thread interrupt. Callers are expected to do that soon after /// acquiring <see cref="s_lock"/>. /// </summary> public bool Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize) { s_lock.VerifyIsLocked(); Debug.Assert(waitInfo != null); Debug.Assert(waitInfo.Thread == RuntimeThread.CurrentThread); Debug.Assert(timeoutMilliseconds >= -1); Debug.Assert(!interruptible || !waitInfo.CheckAndResetPendingInterrupt); bool needToWait = false; try { if (IsSignaled) { bool isAbandoned = IsAbandonedMutex; AcceptSignal(waitInfo); if (isAbandoned) { throw new AbandonedMutexException(); } return(true); } if (IsMutex && _ownershipInfo.Thread == waitInfo.Thread) { if (!_ownershipInfo.CanIncrementReacquireCount) { throw new OverflowException(SR.Overflow_MutexReacquireCount); } _ownershipInfo.IncrementReacquireCount(); return(true); } if (timeoutMilliseconds == 0) { return(false); } WaitableObject[] waitableObjects = waitInfo.GetWaitedObjectArray(1); waitableObjects[0] = this; waitInfo.RegisterWait(1, prioritize, isWaitForAll: false); needToWait = true; } finally { // Once the wait function is called, it will release the lock if (!needToWait) { s_lock.Release(); } } return (waitInfo.Wait( timeoutMilliseconds, interruptible, waitHandlesForAbandon: null, isSleep: false) != WaitHandle.WaitTimeout); }
public static int Wait( RuntimeThread currentThread, WaitableObject waitableObject0, WaitableObject waitableObject1, bool waitForAll, int timeoutMilliseconds, bool interruptible = true, bool prioritize = false) { Debug.Assert(currentThread == RuntimeThread.CurrentThread); Debug.Assert(waitableObject0 != null); Debug.Assert(waitableObject1 != null); Debug.Assert(waitableObject1 != waitableObject0); Debug.Assert(timeoutMilliseconds >= -1); ThreadWaitInfo waitInfo = currentThread.WaitInfo; int count = 2; WaitableObject[] waitableObjects = waitInfo.GetWaitedObjectArray(count); waitableObjects[0] = waitableObject0; waitableObjects[1] = waitableObject1; return (WaitableObject.Wait( waitableObjects, count, waitForAll, waitInfo, timeoutMilliseconds, interruptible, prioritize, waitHandlesForAbandon: null)); }
/// <summary> /// This function does not check for a pending thread interrupt. Callers are expected to do that soon after /// acquiring <see cref="s_lock"/>. /// </summary> public int Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize, ref LockHolder lockHolder) { s_lock.VerifyIsLocked(); Debug.Assert(waitInfo != null); Debug.Assert(waitInfo.Thread == Thread.CurrentThread); Debug.Assert(timeoutMilliseconds >= -1); Debug.Assert(!interruptible || !waitInfo.CheckAndResetPendingInterrupt); if (IsSignaled) { bool isAbandoned = IsAbandonedMutex; AcceptSignal(waitInfo); return(isAbandoned ? WaitHandle.WaitAbandoned : WaitHandle.WaitSuccess); } if (IsMutex && _ownershipInfo != null && _ownershipInfo.Thread == waitInfo.Thread) { if (!_ownershipInfo.CanIncrementReacquireCount) { lockHolder.Dispose(); throw new OverflowException(SR.Overflow_MutexReacquireCount); } _ownershipInfo.IncrementReacquireCount(); return(WaitHandle.WaitSuccess); } if (timeoutMilliseconds == 0) { return(WaitHandle.WaitTimeout); } WaitableObject?[] waitableObjects = waitInfo.GetWaitedObjectArray(1); waitableObjects[0] = this; waitInfo.RegisterWait(1, prioritize, isWaitForAll: false); return (waitInfo.Wait( timeoutMilliseconds, interruptible, isSleep: false, ref lockHolder)); }
public static int Wait( Span <IntPtr> waitHandles, bool waitForAll, int timeoutMilliseconds) { Debug.Assert(waitHandles != null); Debug.Assert(waitHandles.Length > 0); Debug.Assert(waitHandles.Length <= WaitHandle.MaxWaitHandles); Debug.Assert(timeoutMilliseconds >= -1); ThreadWaitInfo waitInfo = Thread.CurrentThread.WaitInfo; WaitableObject?[] waitableObjects = waitInfo.GetWaitedObjectArray(waitHandles.Length); bool success = false; try { for (int i = 0; i < waitHandles.Length; ++i) { Debug.Assert(waitHandles[i] != IntPtr.Zero); WaitableObject waitableObject = HandleManager.FromHandle(waitHandles[i]); if (waitForAll) { // Check if this is a duplicate, as wait-for-all does not support duplicates. Including the parent // loop, this becomes a brute force O(n^2) search, which is intended since the typical array length is // short enough that this would actually be faster than other alternatives. Also, the worst case is not // so bad considering that the array length is limited by <see cref="WaitHandle.MaxWaitHandles"/>. for (int j = 0; j < i; ++j) { if (waitableObject == waitableObjects[j]) { throw new DuplicateWaitObjectException("waitHandles[" + i + ']'); } } } waitableObjects[i] = waitableObject; } success = true; } finally { if (!success) { for (int i = 0; i < waitHandles.Length; ++i) { waitableObjects[i] = null; } } } if (waitHandles.Length == 1) { WaitableObject waitableObject = waitableObjects[0] !; waitableObjects[0] = null; return (waitableObject.Wait(waitInfo, timeoutMilliseconds, interruptible: true, prioritize: false)); } return (WaitableObject.Wait( waitableObjects, waitHandles.Length, waitForAll, waitInfo, timeoutMilliseconds, interruptible: true, prioritize: false)); }
public static int Wait( RuntimeThread currentThread, SafeWaitHandle[] safeWaitHandles, WaitHandle[] waitHandles, bool waitForAll, int timeoutMilliseconds) { Debug.Assert(currentThread == RuntimeThread.CurrentThread); Debug.Assert(safeWaitHandles != null); Debug.Assert(safeWaitHandles.Length >= waitHandles.Length); Debug.Assert(waitHandles.Length > 0); Debug.Assert(waitHandles.Length <= WaitHandle.MaxWaitHandles); Debug.Assert(timeoutMilliseconds >= -1); ThreadWaitInfo waitInfo = currentThread.WaitInfo; if (waitInfo.CheckAndResetPendingInterrupt) { throw new ThreadInterruptedException(); } int count = waitHandles.Length; WaitableObject[] waitableObjects = waitInfo.GetWaitedObjectArray(count); bool success = false; try { for (int i = 0; i < count; ++i) { Debug.Assert(safeWaitHandles[i] != null); WaitableObject waitableObject = HandleManager.FromHandle(safeWaitHandles[i].DangerousGetHandle()); if (waitForAll) { /// Check if this is a duplicate, as wait-for-all does not support duplicates. Including the parent /// loop, this becomes a brute force O(n^2) search, which is intended since the typical array length is /// short enough that this would actually be faster than other alternatives. Also, the worst case is not /// so bad considering that the array length is limited by <see cref="WaitHandle.MaxWaitHandles"/>. for (int j = 0; j < i; ++j) { if (waitableObject == waitableObjects[j]) { throw new DuplicateWaitObjectException("waitHandles[" + i + ']'); } } } waitableObjects[i] = waitableObject; } success = true; } finally { if (!success) { for (int i = 0; i < count; ++i) { waitableObjects[i] = null; } } } if (count == 1) { WaitableObject waitableObject = waitableObjects[0]; waitableObjects[0] = null; return(waitableObject.Wait(waitInfo, timeoutMilliseconds) ? 0 : WaitHandle.WaitTimeout); } return (WaitableObject.Wait( waitableObjects, count, waitForAll, waitInfo, timeoutMilliseconds, waitHandles)); }