summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStephen Toub <stoub@microsoft.com>2019-04-01 22:55:10 -0400
committerGitHub <noreply@github.com>2019-04-01 22:55:10 -0400
commit2f4981fdeff5b9258bb8a873fe3d47f9d37b5c4c (patch)
tree622bad9d5509f02f7c1a04ccdd6cf54be2b96327 /src
parent338bc3472b1ab6cda3767d830c37fb329b33df9f (diff)
downloadcoreclr-2f4981fdeff5b9258bb8a873fe3d47f9d37b5c4c.tar.gz
coreclr-2f4981fdeff5b9258bb8a873fe3d47f9d37b5c4c.tar.bz2
coreclr-2f4981fdeff5b9258bb8a873fe3d47f9d37b5c4c.zip
Nullable: WaitHandles (#23604)
Diffstat (limited to 'src')
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs3
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Mutex.cs3
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Semaphore.cs3
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs5
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/AutoResetEvent.cs1
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs9
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ManualResetEvent.cs1
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs7
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Mutex.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs7
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs11
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/WaitHandle.cs49
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs6
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/WaitHandle.CoreCLR.cs1
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;