/// <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));
            }
Ejemplo n.º 4
0
        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));
        }
Ejemplo n.º 5
0
        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));
        }