Exemplo n.º 1
0
        internal static unsafe int WaitForSingleObject(IntPtr handle, int millisecondsTimeout)
        {
            SynchronizationContext context = RuntimeThread.CurrentThread.SynchronizationContext;
            bool useSyncContextWait        = (context != null) && context.IsWaitNotificationRequired();

            if (useSyncContextWait)
            {
                var handles = new IntPtr[1] {
                    handle
                };
                return(context.Wait(handles, false, millisecondsTimeout));
            }

            return(WaitForMultipleObjectsIgnoringSyncContext(&handle, 1, false, millisecondsTimeout));
        }
Exemplo n.º 2
0
        private bool WaitOneNoCheck(int millisecondsTimeout)
        {
            Debug.Assert(millisecondsTimeout >= -1);

            // The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally
            // to ensure that one instance is used in all places in this method
            SafeWaitHandle waitHandle = _waitHandle;

            if (waitHandle == null)
            {
                // Throw ObjectDisposedException for backward compatibility even though it is not be representative of the issue
                throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic);
            }

            bool success = false;

            try
            {
                int waitResult;

                waitHandle.DangerousAddRef(ref success);

                SynchronizationContext context = SynchronizationContext.Current;
                if (context != null && context.IsWaitNotificationRequired())
                {
                    waitResult = context.Wait(new[] { waitHandle.DangerousGetHandle() }, false, millisecondsTimeout);
                }
                else
                {
                    waitResult = WaitOneCore(waitHandle.DangerousGetHandle(), millisecondsTimeout);
                }

                if (waitResult == WaitAbandoned)
                {
                    throw new AbandonedMutexException();
                }

                return(waitResult != WaitTimeout);
            }
            finally
            {
                if (success)
                {
                    waitHandle.DangerousRelease();
                }
            }
        }
Exemplo n.º 3
0
        /*========================================================================
        ** Waits for signal from all the objects.
        ** timeout indicates how long to wait before the method returns.
        ** This method will return either when all the object have been pulsed
        ** or timeout milliseonds have elapsed.
        ** ========================================================================*/
        private static int WaitMultiple(
            RuntimeThread currentThread,
            SafeWaitHandle[] safeWaitHandles,
            int count,
            int millisecondsTimeout,
            bool waitAll)
        {
            Debug.Assert(currentThread == RuntimeThread.CurrentThread);
            Debug.Assert(safeWaitHandles != null);
            Debug.Assert(safeWaitHandles.Length >= count);

            // If we need to call SynchronizationContext.Wait method, always allocate a new IntPtr[]
            SynchronizationContext context = currentThread.SynchronizationContext;
            bool useSyncContextWait        = (context != null) && context.IsWaitNotificationRequired();

            IntPtr[] rentedHandles = useSyncContextWait ? null : currentThread.RentWaitedHandleArray(count);
            IntPtr[] handles       = rentedHandles ?? new IntPtr[count];
            try
            {
                for (int i = 0; i < count; i++)
                {
                    handles[i] = safeWaitHandles[i].DangerousGetHandle();
                }

                if (useSyncContextWait)
                {
                    return(context.Wait(handles, waitAll, millisecondsTimeout));
                }

                unsafe
                {
                    fixed(IntPtr *pHandles = handles)
                    {
                        return(WaitForMultipleObjectsIgnoringSyncContext(pHandles, count, waitAll, millisecondsTimeout, true));
                    }
                }
            }
            finally
            {
                if (rentedHandles != null)
                {
                    currentThread.ReturnWaitedHandleArray(rentedHandles);
                }
            }
        }
Exemplo n.º 4
0
        private static int WaitMultiple(ReadOnlySpan <WaitHandle> waitHandles, bool waitAll, int millisecondsTimeout)
        {
            if (waitHandles == null)
            {
                throw new ArgumentNullException(nameof(waitHandles), SR.ArgumentNull_Waithandles);
            }
            if (waitHandles.Length == 0)
            {
                //
                // Some history: in CLR 1.0 and 1.1, we threw ArgumentException in this case, which was correct.
                // Somehow, in 2.0, this became ArgumentNullException.  This was not fixed until Silverlight 2,
                // which went back to ArgumentException.
                //
                // Now we're in a bit of a bind.  Backward-compatibility requires us to keep throwing ArgumentException
                // in CoreCLR, and ArgumentNullException in the desktop CLR.  This is ugly, but so is breaking
                // user code.
                //
                throw new ArgumentException(SR.Argument_EmptyWaithandleArray, nameof(waitHandles));
            }
            if (waitHandles.Length > MaxWaitHandles)
            {
                throw new NotSupportedException(SR.NotSupported_MaxWaitHandles);
            }
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
            }

            SynchronizationContext context = SynchronizationContext.Current;
            bool useWaitContext            = context != null && context.IsWaitNotificationRequired();

            SafeWaitHandle[] safeWaitHandles = RentSafeWaitHandleArray(waitHandles.Length);

            try
            {
                int waitResult;

                if (useWaitContext)
                {
                    IntPtr[] unsafeWaitHandles = new IntPtr[waitHandles.Length];
                    ObtainSafeWaitHandles(waitHandles, safeWaitHandles, unsafeWaitHandles);
                    waitResult = context.Wait(unsafeWaitHandles, waitAll, millisecondsTimeout);
                }
                else
                {
                    Span <IntPtr> unsafeWaitHandles = stackalloc IntPtr[waitHandles.Length];
                    ObtainSafeWaitHandles(waitHandles, safeWaitHandles, unsafeWaitHandles);
                    waitResult = WaitMultipleIgnoringSyncContext(unsafeWaitHandles, waitAll, millisecondsTimeout);
                }

                if (waitResult >= WaitAbandoned && waitResult < WaitAbandoned + waitHandles.Length)
                {
                    if (waitAll)
                    {
                        // In the case of WaitAll the OS will only provide the information that mutex was abandoned.
                        // It won't tell us which one.  So we can't set the Index or provide access to the Mutex
                        throw new AbandonedMutexException();
                    }

                    waitResult -= WaitAbandoned;
                    throw new AbandonedMutexException(waitResult, waitHandles[waitResult]);
                }

                return(waitResult);
            }
            finally
            {
                for (int i = 0; i < waitHandles.Length; ++i)
                {
                    if (safeWaitHandles[i] != null)
                    {
                        safeWaitHandles[i].DangerousRelease();
                        safeWaitHandles[i] = null;
                    }
                }

                ReturnSafeWaitHandleArray(safeWaitHandles);
            }
        }