Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Moved SafeWaitHandle and cancellationToken to shared #18662

Merged
merged 9 commits into from
Jun 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/System.Private.CoreLib/System.Private.CoreLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,9 @@
<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" />
Expand Down Expand Up @@ -488,7 +486,6 @@
<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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<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" />
Expand Down Expand Up @@ -580,6 +581,7 @@
<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" />
Expand All @@ -594,6 +596,7 @@
<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" />
Expand Down Expand Up @@ -724,7 +727,6 @@
<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" />
Expand Down Expand Up @@ -810,6 +812,8 @@
<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" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -29,14 +30,14 @@ 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>
Expand Down Expand Up @@ -136,7 +137,7 @@ public CancellationTokenRegistration Register(Action callback) =>
Register(
s_actionToActionObjShunt,
callback ?? throw new ArgumentNullException(nameof(callback)),
useSyncContext: false,
useSynchronizationContext: false,
useExecutionContext: true);

/// <summary>
Expand Down Expand Up @@ -189,7 +190,7 @@ public CancellationTokenRegistration Register(Action callback, bool useSynchroni
/// 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
Expand Down Expand Up @@ -222,19 +223,43 @@ public CancellationTokenRegistration Register(Action<object> 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<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.
}

Expand Down Expand Up @@ -305,9 +330,7 @@ private CancellationTokenRegistration Register(Action<object> callback, object s
public void ThrowIfCancellationRequested()
{
if (IsCancellationRequested)
{
ThrowOperationCanceledException();
}
}

// Throws an OCE; separated out to enable better inlining of ThrowIfCancellationRequested
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
/// <summary>
Expand Down Expand Up @@ -77,7 +65,7 @@ public class SemaphoreSlim : IDisposable
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 =
Expand All @@ -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

Expand Down Expand Up @@ -238,7 +227,7 @@ public void Wait(CancellationToken cancellationToken)
/// 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
Expand Down Expand Up @@ -267,7 +256,7 @@ public bool Wait(TimeSpan 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)
{
Expand Down Expand Up @@ -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
Expand All @@ -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 { }
Expand Down Expand Up @@ -487,7 +475,6 @@ private bool WaitUntilCountOrTimeout(int millisecondsTimeout, uint startTime, Ca
return false;
}
}

// ** the actual wait **
bool waitSuccessful = Monitor.Wait(m_lockObj, remainingWaitMilliseconds);

Expand Down Expand Up @@ -578,7 +565,7 @@ public Task<bool> WaitAsync(int millisecondsTimeout)
/// </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"/>.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: The original version of this comment looked right. The new version does not make sense to me.

/// an infinite time-out -or- timeout is greater than <see cref="System.Int32.MaxValue"/>.
/// </exception>
public Task<bool> WaitAsync(TimeSpan timeout)
{
Expand All @@ -599,7 +586,7 @@ 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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -929,8 +916,6 @@ protected virtual void Dispose(bool disposing)
}
}



/// <summary>
/// Private helper method to wake up waiters when a cancellationToken gets canceled.
/// </summary>
Expand All @@ -956,7 +941,6 @@ private void CheckDispose()
throw new ObjectDisposedException(null, SR.SemaphoreSlim_Disposed);
}
}

#endregion
}
}

This file was deleted.

2 changes: 0 additions & 2 deletions src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading