<Compile Include="$(BclSourcesRoot)\System\Threading\WaitHandle.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\SpinLock.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\ThreadLocal.cs" />
- <Compile Include="$(BclSourcesRoot)\System\Threading\SemaphoreSlim.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\ManualResetEventSlim.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\CancellationTokenRegistration.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\CancellationTokenSource.cs" />
- <Compile Include="$(BclSourcesRoot)\System\Threading\CancellationToken.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Tasks\future.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Tasks\FutureFactory.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Tasks\Task.cs" />
<Compile Include="$(BclSourcesRoot)\System\Collections\ObjectModel\ReadOnlyDictionary.cs" />
</ItemGroup>
<ItemGroup>
- <Compile Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeWaitHandle.cs" />
<Compile Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeRegistryHandle.cs" />
</ItemGroup>
<ItemGroup>
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr handle);
}
}
--- /dev/null
+// 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);
+ }
+}
--- /dev/null
+// 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);
+ }
+ }
+}
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\CriticalHandleZeroOrMinusOneIsInvalid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeHandleMinusOneIsInvalid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeHandleZeroOrMinusOneIsInvalid.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeWaitHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Action.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\AccessViolationException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ApplicationException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ApartmentState.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\AsyncLocal.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\AutoResetEvent.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\CancellationToken.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\DeferredDisposableLifetime.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\EventResetMode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\EventWaitHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ReaderWriterLockSlim.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Semaphore.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SemaphoreFullException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\SemaphoreSlim.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SendOrPostCallback.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinWait.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SynchronizationLockException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.BOOL.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.Libraries.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CancelIoEx.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CloseHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FileAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FILE_INFO_BY_HANDLE_CLASS.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FileTypes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs" />
</ItemGroup>
<ItemGroup Condition="$(TargetsWindows) or '$(FeaturePal)'=='true'">
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeWaitHandle.Windows.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CloseHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Constants.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.Errors.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FormatMessage.cs" />
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Runtime.CompilerServices;
namespace System.Threading
{
[DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}")]
public readonly struct CancellationToken
{
- private readonly static Action<object> 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<object> s_actionToActionObjShunt = obj => ((Action)obj)();
+
/// <summary>
/// Returns an empty CancellationToken value.
/// </summary>
Register(
s_actionToActionObjShunt,
callback ?? throw new ArgumentNullException(nameof(callback)),
- useSyncContext: false,
+ useSynchronizationContext: false,
useExecutionContext: true);
/// <summary>
/// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
public CancellationTokenRegistration Register(Action<object> callback, object state) =>
- Register(callback, state, useSyncContext: false, useExecutionContext: true);
+ Register(callback, state, useSynchronizationContext: false, useExecutionContext: true);
/// <summary>
/// Registers a delegate that will be called when this
// 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<object> callback, object state) =>
- Register(callback, state, useSyncContext: false, useExecutionContext: false);
+ Register(callback, state, useSynchronizationContext: false, useExecutionContext: false);
- // the real work..
- private CancellationTokenRegistration Register(Action<object> callback, object state, bool useSyncContext, bool useExecutionContext)
+ /// <summary>
+ /// Registers a delegate that will be called when this
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// 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.
+ /// </para>
+ /// </remarks>
+ /// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
+ /// <param name="state">The state to pass to the <paramref name="callback"/> when the delegate is invoked. This may be null.</param>
+ /// <param name="useSynchronizationContext">A Boolean value that indicates whether to capture
+ /// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
+ /// when invoking the <paramref name="callback"/>.</param>
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// be used to unregister the callback.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+#if CORECLR
+ private
+#else
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public
+#endif
+ CancellationTokenRegistration Register(Action<object> 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.
}
public void ThrowIfCancellationRequested()
{
if (IsCancellationRequested)
- {
ThrowOperationCanceledException();
- }
}
// Throws an OCE; separated out to enable better inlining of ThrowIfCancellationRequested
// 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
{
/// <summary>
private TaskNode m_asyncTail;
// A pre-completed task with Result==true
- private readonly static Task<bool> s_trueTask =
+ private static readonly Task<bool> s_trueTask =
new Task<bool>(false, true, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default);
// A pre-completed task with Result==false
private readonly static Task<bool> s_falseTask =
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
/// otherwise, false.</returns>
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
/// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
- /// than <see cref="System.int.MaxValue"/>.</exception>
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
public bool Wait(TimeSpan timeout)
{
// Validate the timeout
/// otherwise, false.</returns>
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
/// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
- /// than <see cref="System.int.MaxValue"/>.</exception>
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
/// <exception cref="System.OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception>
public bool Wait(TimeSpan timeout, 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
}
}
}
-
// 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 { }
return false;
}
}
-
// ** the actual wait **
bool waitSuccessful = Monitor.Wait(m_lockObj, remainingWaitMilliseconds);
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents
- /// an infinite time-out -or- timeout is greater than <see cref="System.int.MaxValue"/>.
+ /// an infinite time-out -or- timeout is greater than <see cref="System.Int32.MaxValue"/>.
/// </exception>
public Task<bool> WaitAsync(TimeSpan timeout)
{
/// </returns>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents
- /// an infinite time-out -or- timeout is greater than <see cref="System.int.MaxValue"/>.
+ /// an infinite time-out -or- timeout is greater than <see cref="System.Int32.MaxValue"/>.
/// </exception>
public Task<bool> WaitAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
{
if (m_waitHandle != null)
{
- m_waitHandle.Close();
+ m_waitHandle.Dispose();
m_waitHandle = null;
}
m_lockObj = null;
}
}
-
-
/// <summary>
/// Private helper method to wake up waiters when a cancellationToken gets canceled.
/// </summary>
throw new ObjectDisposedException(null, SR.SemaphoreSlim_Disposed);
}
}
-
#endregion
}
}
+++ /dev/null
-// 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);
- }
- }
-}
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);
}
}
-
-
/// <summary>
/// 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.
{
internal static readonly Action<object> 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
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();