/// <summary>
        /// Signal <see cref="UserUnregisterWaitHandle"/> if it has not been signaled yet and is a valid handle.
        /// </summary>
        private void SignalUserWaitHandle()
        {
            _callbackLock.VerifyIsLocked();
            SafeWaitHandle handle      = UserUnregisterWaitHandle;
            IntPtr         handleValue = UserUnregisterWaitHandleValue;

            try
            {
                if (handleValue != IntPtr.Zero && handleValue != (IntPtr)(-1))
                {
                    Debug.Assert(handleValue == handle.DangerousGetHandle());
#if PLATFORM_WINDOWS
                    Interop.Kernel32.SetEvent(handle);
#else
                    WaitSubsystem.SetEvent(handleValue);
#endif
                }
            }
            finally
            {
                handle?.DangerousRelease();
                _callbacksComplete?.Set();
                _unregistered = true;
            }
        }
        /// <summary>
        /// Signal <see cref="UserUnregisterWaitHandle"/> if it has not been signaled yet and is a valid handle.
        /// </summary>
        private void SignalUserWaitHandle()
        {
            _callbackLock.VerifyIsLocked();
            SafeWaitHandle handle      = UserUnregisterWaitHandle;
            IntPtr         handleValue = UserUnregisterWaitHandleValue;

            try
            {
                if (handleValue != IntPtr.Zero && handleValue != (IntPtr)(-1))
                {
                    EventWaitHandle.Set(handleValue);
                }
            }
            finally
            {
                handle?.DangerousRelease();
                _callbacksComplete?.Set();
                _unregistered = true;
            }
        }
Exemple #3
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 ?? 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();
                }
            }
        }
Exemple #4
0
        private int ReleaseCore(int releaseCount)
        {
            // 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)
            {
                ThrowInvalidHandleException();
            }

            waitHandle.DangerousAddRef();
            try
            {
                return(ReleaseCore(waitHandle.DangerousGetHandle(), releaseCount));
            }
            finally
            {
                waitHandle.DangerousRelease();
            }
        }
        public bool Reset()
        {
            // The field value is modifiable via <see cref="SafeWaitHandle"/>, save it locally to ensure that ref modification
            // is done on the same instance
            SafeWaitHandle waitHandle = _waitHandle;

            if (waitHandle == null)
            {
                ThrowInvalidHandleException();
            }

            waitHandle.DangerousAddRef();
            try
            {
                return(ResetCore(_waitHandle.DangerousGetHandle()));
            }
            finally
            {
                waitHandle.DangerousRelease();
            }
        }
        /// <summary>
        /// Signal <see cref="UserUnregisterWaitHandle"/> if it has not been signaled yet and is a valid handle.
        /// </summary>
        private void SignalUserWaitHandle()
        {
            s_callbackLock.VerifyIsLocked();
            SafeWaitHandle?handle      = UserUnregisterWaitHandle;
            IntPtr         handleValue = UserUnregisterWaitHandleValue;

            try
            {
                if (handleValue != IntPtr.Zero && handleValue != InvalidHandleValue)
                {
                    Debug.Assert(handleValue == handle !.DangerousGetHandle());
                    EventWaitHandle.Set(handle);
                }
            }
            finally
            {
                handle?.DangerousRelease();
                _callbacksComplete?.Set();
                _unregistered = true;
            }
        }
Exemple #7
0
        public void ReleaseMutex()
        {
            // 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)
            {
                ThrowInvalidHandleException();
            }

            waitHandle.DangerousAddRef();
            try
            {
                WaitSubsystem.ReleaseMutex(waitHandle.DangerousGetHandle());
            }
            finally
            {
                waitHandle.DangerousRelease();
            }
        }
Exemple #8
0
        private void FinishUnregistering()
        {
            Debug.Assert(_unregistering);

            // Wait for outstanding wait callbacks to complete
            Interop.Kernel32.WaitForThreadpoolWaitCallbacks(_tpWait, false);

            // Now it is safe to dispose resources
            Interop.Kernel32.CloseThreadpoolWait(_tpWait);
            _tpWait = IntPtr.Zero;

            if (_gcHandle.IsAllocated)
            {
                _gcHandle.Free();
            }

            Debug.Assert(_waitHandle != null);
            _waitHandle.DangerousRelease();
            _waitHandle = null;

            GC.SuppressFinalize(this);
        }
Exemple #9
0
        private bool WaitOneCore(int millisecondsTimeout, bool interruptible = true)
        {
            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);
            }

            waitHandle.DangerousAddRef();
            try
            {
                return(WaitOneCore(waitHandle.DangerousGetHandle(), millisecondsTimeout, interruptible));
            }
            finally
            {
                waitHandle.DangerousRelease();
            }
        }
Exemple #10
0
        private void SignalNoCallbacksRunning()
        {
            object toSignal = _notifyWhenNoCallbacksRunning;

            Debug.Assert(toSignal is WaitHandle || toSignal is Task <bool>);

            if (toSignal is WaitHandle wh)
            {
                SafeWaitHandle waitHandle = wh.SafeWaitHandle;
                waitHandle.DangerousAddRef();
                try
                {
                    WaitSubsystem.SetEvent(waitHandle.DangerousGetHandle());
                }
                finally
                {
                    waitHandle.DangerousRelease();
                }
            }
            else
            {
                ((Task <bool>)toSignal).TrySetResult(true);
            }
        }
Exemple #11
0
        /// <summary>
        /// Obtains all of the corresponding safe wait handles and adds a ref to each. Since the <see cref="SafeWaitHandle"/>
        /// property is publically modifiable, this makes sure that we add and release refs one the same set of safe wait
        /// handles to keep them alive during a multi-wait operation.
        /// </summary>
        private static SafeWaitHandle[] ObtainSafeWaitHandles(
            RuntimeThread currentThread,
            WaitHandle[] waitHandles,
            int numWaitHandles,
            out SafeWaitHandle[] rentedSafeWaitHandles)
        {
            Debug.Assert(currentThread == RuntimeThread.CurrentThread);
            Debug.Assert(waitHandles != null);
            Debug.Assert(numWaitHandles > 0);
            Debug.Assert(numWaitHandles <= MaxWaitHandles);
            Debug.Assert(numWaitHandles <= waitHandles.Length);

            rentedSafeWaitHandles = currentThread.RentWaitedSafeWaitHandleArray(numWaitHandles);
            SafeWaitHandle[] safeWaitHandles = rentedSafeWaitHandles ?? new SafeWaitHandle[numWaitHandles];
            bool             success         = false;

            try
            {
                for (int i = 0; i < numWaitHandles; ++i)
                {
                    WaitHandle waitHandle = waitHandles[i];
                    if (waitHandle == null)
                    {
                        throw new ArgumentNullException("waitHandles[" + i + ']', SR.ArgumentNull_ArrayElement);
                    }

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

                    safeWaitHandle.DangerousAddRef();
                    safeWaitHandles[i] = safeWaitHandle;
                }
                success = true;
            }
            finally
            {
                if (!success)
                {
                    for (int i = 0; i < numWaitHandles; ++i)
                    {
                        SafeWaitHandle safeWaitHandle = safeWaitHandles[i];
                        if (safeWaitHandle == null)
                        {
                            break;
                        }
                        safeWaitHandle.DangerousRelease();
                        safeWaitHandles[i] = null;
                    }

                    if (rentedSafeWaitHandles != null)
                    {
                        currentThread.ReturnWaitedSafeWaitHandleArray(rentedSafeWaitHandles);
                    }
                }
            }

            return(safeWaitHandles);
        }
Exemple #12
0
        /// <summary>
        /// Obtains all of the corresponding safe wait handles and adds a ref to each. Since the <see cref="SafeWaitHandle"/>
        /// property is publically modifiable, this makes sure that we add and release refs one the same set of safe wait
        /// handles to keep them alive during a multi-wait operation.
        /// </summary>
        private static void ObtainSafeWaitHandles(
            ReadOnlySpan <WaitHandle> waitHandles,
            Span <SafeWaitHandle> safeWaitHandles,
            Span <IntPtr> unsafeWaitHandles)
        {
            Debug.Assert(waitHandles != null);
            Debug.Assert(waitHandles.Length > 0);
            Debug.Assert(waitHandles.Length <= MaxWaitHandles);

            bool           lastSuccess        = true;
            SafeWaitHandle lastSafeWaitHandle = null;

            try
            {
                for (int i = 0; i < waitHandles.Length; ++i)
                {
                    WaitHandle waitHandle = waitHandles[i];
                    if (waitHandle == null)
                    {
                        throw new ArgumentNullException("waitHandles[" + i + ']', SR.ArgumentNull_ArrayElement);
                    }

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

                    lastSafeWaitHandle = safeWaitHandle;
                    lastSuccess        = false;
                    safeWaitHandle.DangerousAddRef(ref lastSuccess);
                    safeWaitHandles[i]   = safeWaitHandle;
                    unsafeWaitHandles[i] = safeWaitHandle.DangerousGetHandle();
                }
            }
            catch
            {
                for (int i = 0; i < waitHandles.Length; ++i)
                {
                    SafeWaitHandle safeWaitHandle = safeWaitHandles[i];
                    if (safeWaitHandle == null)
                    {
                        break;
                    }
                    safeWaitHandle.DangerousRelease();
                    safeWaitHandles[i] = null;
                    if (safeWaitHandle == lastSafeWaitHandle)
                    {
                        lastSafeWaitHandle = null;
                        lastSuccess        = true;
                    }
                }

                if (!lastSuccess)
                {
                    lastSafeWaitHandle.DangerousRelease();
                }

                throw;
            }
        }
Exemple #13
0
        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // WARNING: Contains a "Constrained Execution Region", modify carefully.
        //
        private static ReturnCode WaitForSingleHandle(
            WaitHandle waitHandle,
            int milliseconds,
            bool userInterface,
            ref uint returnValue,
            ref Result error
            )
        {
            SafeWaitHandle safeWaitHandle = null;
            bool           success        = false;

            RuntimeHelpers.PrepareConstrainedRegions();

            try
            {
                if (waitHandle == null)
                {
                    error = "invalid wait handle";
                    return(ReturnCode.Error);
                }

                safeWaitHandle = waitHandle.SafeWaitHandle;

                if (safeWaitHandle == null)
                {
                    error = "invalid safe wait handle";
                    return(ReturnCode.Error);
                }

                safeWaitHandle.DangerousAddRef(ref success);

                if (!success)
                {
                    error = "failed to add reference to safe wait handle";
                    return(ReturnCode.Error);
                }

                IntPtr[] handles = { safeWaitHandle.DangerousGetHandle() };

                if (handles[0] == IntPtr.Zero)
                {
                    error = "failed to get native handle from safe wait handle";
                    return(ReturnCode.Error);
                }

                if (userInterface)
                {
                    returnValue = UnsafeNativeMethods.MsgWaitForMultipleObjectsEx(
                        1, handles, (uint)milliseconds, UnsafeNativeMethods.QS_ALLINPUT,
                        UnsafeNativeMethods.MWMO_DEFAULT);
                }
                else
                {
                    returnValue = UnsafeNativeMethods.WaitForMultipleObjectsEx(
                        1, handles, false, (uint)milliseconds, true);
                }

                return(ReturnCode.Ok);
            }
            catch (Exception e)
            {
                if (traceException)
                {
                    TraceOps.DebugTrace(
                        e, typeof(WindowOps).Name,
                        TracePriority.NativeError);
                }

                error = e;
            }
            finally
            {
                if (success)
                {
                    safeWaitHandle.DangerousRelease();
                    success = false;
                }
            }

            return(ReturnCode.Error);
        }