diff --git a/src/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/System.Private.CoreLib.csproj
index 9e8d9f7fe732..986d273addc1 100644
--- a/src/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -398,11 +398,9 @@
-
-
@@ -488,7 +486,6 @@
-
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs
index 96ed922a846d..ff41f939f1c6 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs
@@ -10,7 +10,6 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr handle);
}
}
diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs
new file mode 100644
index 000000000000..66f17f0af709
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.Win32.SafeHandles
+{
+ public sealed partial class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ protected override bool ReleaseHandle() => Interop.Kernel32.CloseHandle(handle);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
new file mode 100644
index 000000000000..edb0cdfcafe7
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// 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;
+
+namespace Microsoft.Win32.SafeHandles
+{
+ public sealed partial class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ // Called by P/Invoke marshaler
+ private SafeWaitHandle() : base(true)
+ {
+ }
+
+ public SafeWaitHandle(IntPtr existingHandle, bool ownsHandle) : base(ownsHandle)
+ {
+ SetHandle(existingHandle);
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
index da36623eaff7..59a3074ab8b7 100644
--- a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
+++ b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
@@ -26,6 +26,7 @@
+
@@ -580,6 +581,7 @@
+
@@ -594,6 +596,7 @@
+
@@ -724,7 +727,6 @@
-
@@ -810,6 +812,8 @@
+
+
diff --git a/src/System.Private.CoreLib/src/System/Threading/CancellationToken.cs b/src/System.Private.CoreLib/shared/System/Threading/CancellationToken.cs
similarity index 89%
rename from src/System.Private.CoreLib/src/System/Threading/CancellationToken.cs
rename to src/System.Private.CoreLib/shared/System/Threading/CancellationToken.cs
index cffaf22cd48d..68e6971a5426 100644
--- a/src/System.Private.CoreLib/src/System/Threading/CancellationToken.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/CancellationToken.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Runtime.CompilerServices;
namespace System.Threading
{
@@ -29,14 +30,14 @@ namespace System.Threading
[DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}")]
public readonly struct CancellationToken
{
- private readonly static Action s_actionToActionObjShunt = obj => ((Action)obj)();
-
// The backing TokenSource.
// if null, it implicitly represents the same thing as new CancellationToken(false).
// When required, it will be instantiated to reflect this.
private readonly CancellationTokenSource _source;
//!! warning. If more fields are added, the assumptions in CreateLinkedToken may no longer be valid
+ private readonly static Action s_actionToActionObjShunt = obj => ((Action)obj)();
+
///
/// Returns an empty CancellationToken value.
///
@@ -136,7 +137,7 @@ public CancellationTokenRegistration Register(Action callback) =>
Register(
s_actionToActionObjShunt,
callback ?? throw new ArgumentNullException(nameof(callback)),
- useSyncContext: false,
+ useSynchronizationContext: false,
useExecutionContext: true);
///
@@ -189,7 +190,7 @@ public CancellationTokenRegistration Register(Action callback, bool useSynchroni
/// be used to unregister the callback.
/// is null.
public CancellationTokenRegistration Register(Action callback, object state) =>
- Register(callback, state, useSyncContext: false, useExecutionContext: true);
+ Register(callback, state, useSynchronizationContext: false, useExecutionContext: true);
///
/// Registers a delegate that will be called when this
@@ -222,19 +223,43 @@ public CancellationTokenRegistration Register(Action callback, object st
// helper for internal registration needs that don't require an EC capture (e.g. creating linked token sources, or registering unstarted TPL tasks)
// has a handy signature, and skips capturing execution context.
internal CancellationTokenRegistration InternalRegisterWithoutEC(Action callback, object state) =>
- Register(callback, state, useSyncContext: false, useExecutionContext: false);
+ Register(callback, state, useSynchronizationContext: false, useExecutionContext: false);
- // the real work..
- private CancellationTokenRegistration Register(Action callback, object state, bool useSyncContext, bool useExecutionContext)
+ ///
+ /// Registers a delegate that will be called when this
+ /// CancellationToken is canceled.
+ ///
+ ///
+ ///
+ /// If this token is already in the canceled state, the
+ /// delegate will be run immediately and synchronously. Any exception the delegate generates will be
+ /// propagated out of this method call.
+ ///
+ ///
+ /// The delegate to be executed when the CancellationToken is canceled.
+ /// The state to pass to the when the delegate is invoked. This may be null.
+ /// A Boolean value that indicates whether to capture
+ /// the current SynchronizationContext and use it
+ /// when invoking the .
+ /// The instance that can
+ /// be used to unregister the callback.
+ /// is null.
+ /// The associated CancellationTokenSource has been disposed.
+#if CORECLR
+ private
+#else
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public
+#endif
+ CancellationTokenRegistration Register(Action callback, object state, bool useSynchronizationContext, bool useExecutionContext)
{
if (callback == null)
- {
throw new ArgumentNullException(nameof(callback));
- }
CancellationTokenSource source = _source;
return source != null ?
- source.InternalRegister(callback, state, useSyncContext ? SynchronizationContext.Current : null, useExecutionContext ? ExecutionContext.Capture() : null) :
+ source.InternalRegister(callback, state, useSynchronizationContext ? SynchronizationContext.Current : null, useExecutionContext ? ExecutionContext.Capture() : null) :
default; // Nothing to do for tokens than can never reach the canceled state. Give back a dummy registration.
}
@@ -305,9 +330,7 @@ private CancellationTokenRegistration Register(Action callback, object s
public void ThrowIfCancellationRequested()
{
if (IsCancellationRequested)
- {
ThrowOperationCanceledException();
- }
}
// Throws an OCE; separated out to enable better inlining of ThrowIfCancellationRequested
diff --git a/src/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs
similarity index 97%
rename from src/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs
rename to src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs
index 9001fcd499d0..6dca573ef991 100644
--- a/src/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs
@@ -2,25 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-//
-//
-// A lightweight semahore class that contains the basic semaphore functions plus some useful functions like interrupt
-// and wait handle exposing to allow waiting on multiple semaphores.
-//
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
using System;
using System.Collections.Generic;
using System.Diagnostics;
-using System.Security;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
-// The class will be part of the current System.Threading namespace
-
namespace System.Threading
{
///
@@ -77,7 +65,7 @@ public class SemaphoreSlim : IDisposable
private TaskNode m_asyncTail;
// A pre-completed task with Result==true
- private readonly static Task s_trueTask =
+ private static readonly Task s_trueTask =
new Task(false, true, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default);
// A pre-completed task with Result==false
private readonly static Task s_falseTask =
@@ -97,8 +85,9 @@ void IThreadPoolWorkItem.ExecuteWorkItem()
bool setSuccessfully = TrySetResult(true);
Debug.Assert(setSuccessfully, "Should have been able to complete task");
}
-
- void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { /* nop */ }
+#if CORECLR
+ void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { /* nop */ }
+#endif
}
#endregion
@@ -238,7 +227,7 @@ public void Wait(CancellationToken cancellationToken)
/// otherwise, false.
/// is a negative
/// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
- /// than .
+ /// than .
public bool Wait(TimeSpan timeout)
{
// Validate the timeout
@@ -267,7 +256,7 @@ public bool Wait(TimeSpan timeout)
/// otherwise, false.
/// is a negative
/// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
- /// than .
+ /// than .
/// was canceled.
public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
{
@@ -348,8 +337,8 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
try
{
// Perf: first spin wait for the count to be positive.
- // This additional amount of spinwaiting in addition
- // to Monitor.Enter()’s spinwaiting has shown measurable perf gains in test scenarios.
+ // This additional amount of spinwaiting in addition
+ // to Monitor.Enter()’s spinwaiting has shown measurable perf gains in test scenarios.
if (m_currentCount == 0)
{
// Monitor.Enter followed by Monitor.Wait is much more expensive than waiting on an event as it involves another
@@ -369,7 +358,6 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
}
}
}
-
// entering the lock and incrementing waiters must not suffer a thread-abort, else we cannot
// clean up m_waitCount correctly, which may lead to deadlock due to non-woken waiters.
try { }
@@ -487,7 +475,6 @@ private bool WaitUntilCountOrTimeout(int millisecondsTimeout, uint startTime, Ca
return false;
}
}
-
// ** the actual wait **
bool waitSuccessful = Monitor.Wait(m_lockObj, remainingWaitMilliseconds);
@@ -578,7 +565,7 @@ public Task WaitAsync(int millisecondsTimeout)
///
///
/// is a negative number other than -1 milliseconds, which represents
- /// an infinite time-out -or- timeout is greater than .
+ /// an infinite time-out -or- timeout is greater than .
///
public Task WaitAsync(TimeSpan timeout)
{
@@ -599,7 +586,7 @@ public Task WaitAsync(TimeSpan timeout)
///
///
/// is a negative number other than -1 milliseconds, which represents
- /// an infinite time-out -or- timeout is greater than .
+ /// an infinite time-out -or- timeout is greater than .
///
public Task WaitAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
@@ -920,7 +907,7 @@ protected virtual void Dispose(bool disposing)
{
if (m_waitHandle != null)
{
- m_waitHandle.Close();
+ m_waitHandle.Dispose();
m_waitHandle = null;
}
m_lockObj = null;
@@ -929,8 +916,6 @@ protected virtual void Dispose(bool disposing)
}
}
-
-
///
/// Private helper method to wake up waiters when a cancellationToken gets canceled.
///
@@ -956,7 +941,6 @@ private void CheckDispose()
throw new ObjectDisposedException(null, SR.SemaphoreSlim_Disposed);
}
}
-
#endregion
}
}
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
deleted file mode 100644
index 1141e6d027ff..000000000000
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/*============================================================
-**
-**
-**
-** A wrapper for Win32 events (mutexes, auto reset events, and
-** manual reset events). Used by WaitHandle.
-**
-**
-===========================================================*/
-
-using System;
-using System.Security;
-using System.Runtime.InteropServices;
-using System.Runtime.CompilerServices;
-using System.Runtime.ConstrainedExecution;
-using System.Runtime.Versioning;
-using Microsoft.Win32;
-using System.Threading;
-
-namespace Microsoft.Win32.SafeHandles
-{
- public sealed class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid
- {
- // Called by P/Invoke marshaler
- private SafeWaitHandle() : base(true)
- {
- }
-
- public SafeWaitHandle(IntPtr existingHandle, bool ownsHandle) : base(ownsHandle)
- {
- SetHandle(existingHandle);
- }
-
- override protected bool ReleaseHandle()
- {
- return Win32Native.CloseHandle(handle);
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs
index a53ec792295a..d1a92a3e0f79 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs
+++ b/src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs
@@ -276,8 +276,6 @@ internal static bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX buffer)
internal static extern uint SysStringByteLen(IntPtr bstr);
#endif
- [DllImport(Interop.Libraries.Kernel32, SetLastError = true)]
- internal static extern bool CloseHandle(IntPtr handle);
[DllImport(Interop.Libraries.Kernel32, SetLastError = true)]
internal static extern unsafe int WriteFile(SafeFileHandle handle, byte* bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero);
diff --git a/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
index d3c811348064..7f41d250b668 100644
--- a/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
@@ -725,8 +725,6 @@ public static CancellationTokenSource CreateLinkedTokenSource(params Cancellatio
}
}
-
-
///
/// Wait for a single callback to complete (or, more specifically, to not be running).
/// It is ok to call this method if the callback has already finished.
@@ -790,17 +788,17 @@ private sealed class LinkedNCancellationTokenSource : CancellationTokenSource
{
internal static readonly Action s_linkedTokenCancelDelegate =
s => ((CancellationTokenSource)s).NotifyCancellation(throwOnFirstException: false); // skip ThrowIfDisposed() check in Cancel()
- private CancellationTokenRegistration[] m_linkingRegistrations;
+ private CancellationTokenRegistration[] _linkingRegistrations;
internal LinkedNCancellationTokenSource(params CancellationToken[] tokens)
{
- m_linkingRegistrations = new CancellationTokenRegistration[tokens.Length];
+ _linkingRegistrations = new CancellationTokenRegistration[tokens.Length];
for (int i = 0; i < tokens.Length; i++)
{
if (tokens[i].CanBeCanceled)
{
- m_linkingRegistrations[i] = tokens[i].InternalRegisterWithoutEC(s_linkedTokenCancelDelegate, this);
+ _linkingRegistrations[i] = tokens[i].InternalRegisterWithoutEC(s_linkedTokenCancelDelegate, this);
}
// Empty slots in the array will be default(CancellationTokenRegistration), which are nops to Dispose.
// Based on usage patterns, such occurrences should also be rare, such that it's not worth resizing
@@ -815,10 +813,10 @@ protected override void Dispose(bool disposing)
return;
}
- CancellationTokenRegistration[] linkingRegistrations = m_linkingRegistrations;
+ CancellationTokenRegistration[] linkingRegistrations = _linkingRegistrations;
if (linkingRegistrations != null)
{
- m_linkingRegistrations = null; // release for GC once we're done enumerating
+ _linkingRegistrations = null; // release for GC once we're done enumerating
for (int i = 0; i < linkingRegistrations.Length; i++)
{
linkingRegistrations[i].Dispose();