diff options
author | Stephen Toub <stoub@microsoft.com> | 2019-04-01 22:55:10 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-01 22:55:10 -0400 |
commit | 2f4981fdeff5b9258bb8a873fe3d47f9d37b5c4c (patch) | |
tree | 622bad9d5509f02f7c1a04ccdd6cf54be2b96327 /src | |
parent | 338bc3472b1ab6cda3767d830c37fb329b33df9f (diff) | |
download | coreclr-2f4981fdeff5b9258bb8a873fe3d47f9d37b5c4c.tar.gz coreclr-2f4981fdeff5b9258bb8a873fe3d47f9d37b5c4c.tar.bz2 coreclr-2f4981fdeff5b9258bb8a873fe3d47f9d37b5c4c.zip |
Nullable: WaitHandles (#23604)
Diffstat (limited to 'src')
15 files changed, 70 insertions, 58 deletions
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs index b562e527e7..8ff166c958 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; @@ -20,7 +21,7 @@ internal static partial class Interop internal static extern bool ResetEvent(SafeWaitHandle handle); [DllImport(Interop.Libraries.Kernel32, EntryPoint = "CreateEventExW", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern SafeWaitHandle CreateEventEx(IntPtr lpSecurityAttributes, string name, uint flags, uint desiredAccess); + internal static extern SafeWaitHandle CreateEventEx(IntPtr lpSecurityAttributes, string? name, uint flags, uint desiredAccess); [DllImport(Interop.Libraries.Kernel32, EntryPoint = "OpenEventW", SetLastError = true, CharSet = CharSet.Unicode)] internal static extern SafeWaitHandle OpenEvent(uint desiredAccess, bool inheritHandle, string name); diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Mutex.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Mutex.cs index cbb306e4f7..ed25668a00 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Mutex.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Mutex.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; @@ -16,7 +17,7 @@ internal static partial class Interop internal static extern SafeWaitHandle OpenMutex(uint desiredAccess, bool inheritHandle, string name); [DllImport(Interop.Libraries.Kernel32, EntryPoint = "CreateMutexExW", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern SafeWaitHandle CreateMutexEx(IntPtr lpMutexAttributes, string name, uint flags, uint desiredAccess); + internal static extern SafeWaitHandle CreateMutexEx(IntPtr lpMutexAttributes, string? name, uint flags, uint desiredAccess); [DllImport(Interop.Libraries.Kernel32, SetLastError = true)] internal static extern bool ReleaseMutex(SafeWaitHandle handle); diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Semaphore.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Semaphore.cs index 94648a7077..f453a255bd 100644 --- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Semaphore.cs +++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Semaphore.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System; using System.Runtime.InteropServices; @@ -14,7 +15,7 @@ internal static partial class Interop internal static extern SafeWaitHandle OpenSemaphore(uint desiredAccess, bool inheritHandle, string name); [DllImport(Libraries.Kernel32, EntryPoint = "CreateSemaphoreExW", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern SafeWaitHandle CreateSemaphoreEx(IntPtr lpSecurityAttributes, int initialCount, int maximumCount, string name, uint flags, uint desiredAccess); + internal static extern SafeWaitHandle CreateSemaphoreEx(IntPtr lpSecurityAttributes, int initialCount, int maximumCount, string? name, uint flags, uint desiredAccess); [DllImport(Interop.Libraries.Kernel32, SetLastError = true)] internal static extern bool ReleaseSemaphore(SafeWaitHandle handle, int releaseCount, out int previousCount); diff --git a/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs b/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs index 7888d8d61b..bedebee683 100644 --- a/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs +++ b/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.InteropServices; namespace System.IO @@ -15,14 +16,14 @@ namespace System.IO /// Converts, resetting it, the last Win32 error into a corresponding <see cref="Exception"/> object, optionally /// including the specified path in the error message. /// </summary> - internal static Exception GetExceptionForLastWin32Error(string path = "") + internal static Exception GetExceptionForLastWin32Error(string? path = "") => GetExceptionForWin32Error(Marshal.GetLastWin32Error(), path); /// <summary> /// Converts the specified Win32 error into a corresponding <see cref="Exception"/> object, optionally /// including the specified path in the error message. /// </summary> - internal static Exception GetExceptionForWin32Error(int errorCode, string path = "") + internal static Exception GetExceptionForWin32Error(int errorCode, string? path = "") { switch (errorCode) { diff --git a/src/System.Private.CoreLib/shared/System/Threading/AutoResetEvent.cs b/src/System.Private.CoreLib/shared/System/Threading/AutoResetEvent.cs index 8320d7ad5a..b8418a94bb 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/AutoResetEvent.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/AutoResetEvent.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Threading { public sealed class AutoResetEvent : EventWaitHandle diff --git a/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs index 62b3e4f9fc..6c7b7155ac 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System; using System.IO; using System.Runtime.InteropServices; @@ -18,7 +19,7 @@ namespace System.Threading SafeWaitHandle = handle; } - private void CreateEventCore(bool initialState, EventResetMode mode, string name, out bool createdNew) + private void CreateEventCore(bool initialState, EventResetMode mode, string? name, out bool createdNew) { #if !PLATFORM_WINDOWS if (name != null) @@ -43,7 +44,7 @@ namespace System.Threading SafeWaitHandle = handle; } - private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle result) + private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle? result) { #if PLATFORM_WINDOWS if (name == null) @@ -76,7 +77,7 @@ namespace System.Threading public bool Reset() { - bool res = Interop.Kernel32.ResetEvent(SafeWaitHandle); + bool res = Interop.Kernel32.ResetEvent(SafeWaitHandle!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384 if (!res) throw Win32Marshal.GetExceptionForLastWin32Error(); return res; @@ -84,7 +85,7 @@ namespace System.Threading public bool Set() { - bool res = Interop.Kernel32.SetEvent(SafeWaitHandle); + bool res = Interop.Kernel32.SetEvent(SafeWaitHandle!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384 if (!res) throw Win32Marshal.GetExceptionForLastWin32Error(); return res; diff --git a/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs index 4cd733b9bd..9b448c51c2 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs @@ -2,7 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable +using System.Diagnostics; using System.IO; namespace System.Threading @@ -14,12 +15,12 @@ namespace System.Threading { } - public EventWaitHandle(bool initialState, EventResetMode mode, string name) : + public EventWaitHandle(bool initialState, EventResetMode mode, string? name) : this(initialState, mode, name, out _) { } - public EventWaitHandle(bool initialState, EventResetMode mode, string name, out bool createdNew) + public EventWaitHandle(bool initialState, EventResetMode mode, string? name, out bool createdNew) { if (mode != EventResetMode.AutoReset && mode != EventResetMode.ManualReset) throw new ArgumentException(SR.Argument_InvalidFlag, nameof(mode)); @@ -29,7 +30,7 @@ namespace System.Threading public static EventWaitHandle OpenExisting(string name) { - EventWaitHandle result; + EventWaitHandle? result; switch (OpenExistingWorker(name, out result)) { case OpenExistingResult.NameNotFound: @@ -39,11 +40,12 @@ namespace System.Threading case OpenExistingResult.PathNotFound: throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, name)); default: + Debug.Assert(result != null, "result should be non-null on success"); return result; } } - public static bool TryOpenExisting(string name, out EventWaitHandle result) + public static bool TryOpenExisting(string name, out EventWaitHandle? result) // TODO-NULLABLE: Try pattern with non-null result when true { return OpenExistingWorker(name, out result) == OpenExistingResult.Success; } diff --git a/src/System.Private.CoreLib/shared/System/Threading/ManualResetEvent.cs b/src/System.Private.CoreLib/shared/System/Threading/ManualResetEvent.cs index 4b8d61f960..4b7442ffaa 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/ManualResetEvent.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/ManualResetEvent.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Threading { public sealed class ManualResetEvent : EventWaitHandle diff --git a/src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs index 26eb4fe5ab..eb1aee594f 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.IO; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; @@ -18,7 +19,7 @@ namespace System.Threading private const uint AccessRights = (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.MUTEX_MODIFY_STATE; - private void CreateMutexCore(bool initiallyOwned, string name, out bool createdNew) + private void CreateMutexCore(bool initiallyOwned, string? name, out bool createdNew) { uint mutexFlags = initiallyOwned ? Interop.Kernel32.CREATE_MUTEX_INITIAL_OWNER : 0; SafeWaitHandle mutexHandle = Interop.Kernel32.CreateMutexEx(IntPtr.Zero, name, mutexFlags, AccessRights); @@ -42,7 +43,7 @@ namespace System.Threading SafeWaitHandle = mutexHandle; } - private static OpenExistingResult OpenExistingWorker(string name, out Mutex result) + private static OpenExistingResult OpenExistingWorker(string name, out Mutex? result) { if (name == null) { @@ -90,7 +91,7 @@ namespace System.Threading // in a Mutex's ACL is MUTEX_ALL_ACCESS (0x1F0001). public void ReleaseMutex() { - if (!Interop.Kernel32.ReleaseMutex(SafeWaitHandle)) + if (!Interop.Kernel32.ReleaseMutex(SafeWaitHandle!)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384 { throw new ApplicationException(SR.Arg_SynchronizationLockException); } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Mutex.cs b/src/System.Private.CoreLib/shared/System/Threading/Mutex.cs index d85242892d..8cfeeb7cfc 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Mutex.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Mutex.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.IO; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; @@ -15,12 +16,12 @@ namespace System.Threading /// </summary> public sealed partial class Mutex : WaitHandle { - public Mutex(bool initiallyOwned, string name, out bool createdNew) + public Mutex(bool initiallyOwned, string? name, out bool createdNew) { CreateMutexCore(initiallyOwned, name, out createdNew); } - public Mutex(bool initiallyOwned, string name) + public Mutex(bool initiallyOwned, string? name) { CreateMutexCore(initiallyOwned, name, out _); } @@ -42,7 +43,7 @@ namespace System.Threading public static Mutex OpenExisting(string name) { - switch (OpenExistingWorker(name, out Mutex result)) + switch (OpenExistingWorker(name, out Mutex? result)) { case OpenExistingResult.NameNotFound: throw new WaitHandleCannotBeOpenedException(); @@ -52,11 +53,12 @@ namespace System.Threading throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, name)); default: + Debug.Assert(result != null, "result should be non-null on success"); return result; } } - public static bool TryOpenExisting(string name, out Mutex result) => + public static bool TryOpenExisting(string name, out Mutex? result) => // TODO-NULLABLE: Try pattern with non-null result when true OpenExistingWorker(name, out result) == OpenExistingResult.Success; } } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs index 8a14f5ef38..f5c2610e10 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32.SafeHandles; using System.Diagnostics; using System.IO; @@ -18,7 +19,7 @@ namespace System.Threading SafeWaitHandle = handle; } - private void CreateSemaphoreCore(int initialCount, int maximumCount, string name, out bool createdNew) + private void CreateSemaphoreCore(int initialCount, int maximumCount, string? name, out bool createdNew) { Debug.Assert(initialCount >= 0); Debug.Assert(maximumCount >= 1); @@ -43,7 +44,7 @@ namespace System.Threading this.SafeWaitHandle = myHandle; } - private static OpenExistingResult OpenExistingWorker(string name, out Semaphore result) + private static OpenExistingResult OpenExistingWorker(string name, out Semaphore? result) { #if PLATFORM_WINDOWS if (name == null) @@ -79,7 +80,7 @@ namespace System.Threading private int ReleaseCore(int releaseCount) { int previousCount; - if (!Interop.Kernel32.ReleaseSemaphore(SafeWaitHandle, releaseCount, out previousCount)) + if (!Interop.Kernel32.ReleaseSemaphore(SafeWaitHandle!, releaseCount, out previousCount)) throw new SemaphoreFullException(); return previousCount; diff --git a/src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs index 6014fcd1c8..9d1b6e4d0d 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs @@ -2,8 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using Microsoft.Win32; using Microsoft.Win32.SafeHandles; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; @@ -15,12 +17,12 @@ namespace System.Threading // Win32 only takes maximum count of int.MaxValue public Semaphore(int initialCount, int maximumCount) : this(initialCount, maximumCount, null) { } - public Semaphore(int initialCount, int maximumCount, string name) : + public Semaphore(int initialCount, int maximumCount, string? name) : this(initialCount, maximumCount, name, out _) { } - public Semaphore(int initialCount, int maximumCount, string name, out bool createdNew) + public Semaphore(int initialCount, int maximumCount, string? name, out bool createdNew) { if (initialCount < 0) throw new ArgumentOutOfRangeException(nameof(initialCount), SR.ArgumentOutOfRange_NeedNonNegNum); @@ -36,7 +38,7 @@ namespace System.Threading public static Semaphore OpenExisting(string name) { - Semaphore result; + Semaphore? result; switch (OpenExistingWorker(name, out result)) { case OpenExistingResult.NameNotFound: @@ -46,11 +48,12 @@ namespace System.Threading case OpenExistingResult.PathNotFound: throw new IOException(SR.Format(SR.IO_PathNotFound_Path, name)); default: + Debug.Assert(result != null, "result should be non-null on success"); return result; } } - public static bool TryOpenExisting(string name, out Semaphore result) => + public static bool TryOpenExisting(string name, out Semaphore? result) => // TODO-NULLABLE: Try pattern with non-null result when true OpenExistingWorker(name, out result) == OpenExistingResult.Success; public int Release() => ReleaseCore(1); diff --git a/src/System.Private.CoreLib/shared/System/Threading/WaitHandle.cs b/src/System.Private.CoreLib/shared/System/Threading/WaitHandle.cs index 3c92bcd4b7..07462c1bc1 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/WaitHandle.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/WaitHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using Microsoft.Win32.SafeHandles; @@ -16,10 +17,10 @@ namespace System.Threading // IMPORTANT: // - Do not add or rearrange fields as the EE depends on this layout. - private SafeWaitHandle _waitHandle; + private SafeWaitHandle? _waitHandle; [ThreadStatic] - private static SafeWaitHandle[] t_safeWaitHandlesForRent; + private static SafeWaitHandle?[]? t_safeWaitHandlesForRent; private protected enum OpenExistingResult { @@ -78,7 +79,7 @@ namespace System.Threading } } - public SafeWaitHandle SafeWaitHandle + public SafeWaitHandle? SafeWaitHandle // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384 { get { @@ -137,12 +138,7 @@ namespace System.Threading // 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); - } + SafeWaitHandle waitHandle = _waitHandle ?? throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic); bool success = false; try @@ -151,7 +147,7 @@ namespace System.Threading waitHandle.DangerousAddRef(ref success); - SynchronizationContext context = SynchronizationContext.Current; + SynchronizationContext? context = SynchronizationContext.Current; if (context != null && context.IsWaitNotificationRequired()) { waitResult = context.Wait(new[] { waitHandle.DangerousGetHandle() }, false, millisecondsTimeout); @@ -177,9 +173,9 @@ namespace System.Threading // Returns an array for storing SafeWaitHandles in WaitMultiple calls. The array // is reused for subsequent calls to reduce GC pressure. - private static SafeWaitHandle[] RentSafeWaitHandleArray(int capacity) + private static SafeWaitHandle?[] RentSafeWaitHandleArray(int capacity) { - SafeWaitHandle[] safeWaitHandles = t_safeWaitHandlesForRent; + SafeWaitHandle?[]? safeWaitHandles = t_safeWaitHandlesForRent; t_safeWaitHandlesForRent = null; @@ -195,7 +191,7 @@ namespace System.Threading return safeWaitHandles; } - private static void ReturnSafeWaitHandleArray(SafeWaitHandle[] safeWaitHandles) + private static void ReturnSafeWaitHandleArray(SafeWaitHandle?[]? safeWaitHandles) => t_safeWaitHandlesForRent = safeWaitHandles; /// <summary> @@ -205,7 +201,7 @@ namespace System.Threading /// </summary> private static void ObtainSafeWaitHandles( ReadOnlySpan<WaitHandle> waitHandles, - Span<SafeWaitHandle> safeWaitHandles, + Span<SafeWaitHandle?> safeWaitHandles, Span<IntPtr> unsafeWaitHandles) { Debug.Assert(waitHandles != null); @@ -213,7 +209,7 @@ namespace System.Threading Debug.Assert(waitHandles.Length <= MaxWaitHandles); bool lastSuccess = true; - SafeWaitHandle lastSafeWaitHandle = null; + SafeWaitHandle? lastSafeWaitHandle = null; try { for (int i = 0; i < waitHandles.Length; ++i) @@ -224,12 +220,9 @@ namespace System.Threading 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 + SafeWaitHandle safeWaitHandle = waitHandle._waitHandle ?? + // Throw ObjectDisposedException for backward compatibility even though it is not representative of the issue throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic); - } lastSafeWaitHandle = safeWaitHandle; lastSuccess = false; @@ -242,7 +235,7 @@ namespace System.Threading { for (int i = 0; i < waitHandles.Length; ++i) { - SafeWaitHandle safeWaitHandle = safeWaitHandles[i]; + SafeWaitHandle? safeWaitHandle = safeWaitHandles[i]; if (safeWaitHandle == null) { break; @@ -258,6 +251,7 @@ namespace System.Threading if (!lastSuccess) { + Debug.Assert(lastSafeWaitHandle != null); lastSafeWaitHandle.DangerousRelease(); } @@ -293,9 +287,9 @@ namespace System.Threading throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1); } - SynchronizationContext context = SynchronizationContext.Current; + SynchronizationContext? context = SynchronizationContext.Current; bool useWaitContext = context != null && context.IsWaitNotificationRequired(); - SafeWaitHandle[] safeWaitHandles = RentSafeWaitHandleArray(waitHandles.Length); + SafeWaitHandle?[]? safeWaitHandles = RentSafeWaitHandleArray(waitHandles.Length); try { @@ -305,7 +299,7 @@ namespace System.Threading { IntPtr[] unsafeWaitHandles = new IntPtr[waitHandles.Length]; ObtainSafeWaitHandles(waitHandles, safeWaitHandles, unsafeWaitHandles); - waitResult = context.Wait(unsafeWaitHandles, waitAll, millisecondsTimeout); + waitResult = context!.Wait(unsafeWaitHandles, waitAll, millisecondsTimeout); } else { @@ -335,7 +329,8 @@ namespace System.Threading { if (safeWaitHandles[i] != null) { - safeWaitHandles[i].DangerousRelease(); + // TODO-NULLABLE: '!' below should not be required + safeWaitHandles[i]!.DangerousRelease(); safeWaitHandles[i] = null; } } @@ -361,8 +356,8 @@ namespace System.Threading // 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 safeWaitHandleToSignal = toSignal._waitHandle; - SafeWaitHandle safeWaitHandleToWaitOn = toWaitOn._waitHandle; + SafeWaitHandle? safeWaitHandleToSignal = toSignal._waitHandle; + SafeWaitHandle? safeWaitHandleToWaitOn = toWaitOn._waitHandle; if (safeWaitHandleToSignal == null || safeWaitHandleToWaitOn == null) { // Throw ObjectDisposedException for backward compatibility even though it is not be representative of the issue diff --git a/src/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs index ef4f6ec403..89030787ed 100644 --- a/src/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs @@ -53,7 +53,7 @@ namespace System.Threading m_internalWaitObject = waitObject; if (waitObject != null) { - m_internalWaitObject.SafeWaitHandle.DangerousAddRef(ref bReleaseNeeded); + m_internalWaitObject.SafeWaitHandle!.DangerousAddRef(ref bReleaseNeeded); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384 } } @@ -83,7 +83,7 @@ namespace System.Threading if (bReleaseNeeded) { Debug.Assert(m_internalWaitObject != null, "Must be non-null for bReleaseNeeded to be true"); - m_internalWaitObject.SafeWaitHandle.DangerousRelease(); + m_internalWaitObject.SafeWaitHandle!.DangerousRelease(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384 bReleaseNeeded = false; } // if result not true don't release/suppress here so finalizer can make another attempt @@ -145,7 +145,7 @@ namespace System.Threading if (bReleaseNeeded) { Debug.Assert(m_internalWaitObject != null, "Must be non-null for bReleaseNeeded to be true"); - m_internalWaitObject.SafeWaitHandle.DangerousRelease(); + m_internalWaitObject.SafeWaitHandle!.DangerousRelease(); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384 bReleaseNeeded = false; } SetHandle(InvalidHandle); diff --git a/src/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs index 97b5c574e3..6bd426c624 100644 --- a/src/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.InteropServices; |