Moved SafeWaitHandle and cancellationToken to shared (dotnet/coreclr#18662)
authorAnirudh Agnihotry <anirudhagnihotry098@gmail.com>
Wed, 27 Jun 2018 18:36:42 +0000 (11:36 -0700)
committerJan Kotas <jkotas@microsoft.com>
Wed, 27 Jun 2018 18:36:42 +0000 (11:36 -0700)
* Moving SafeWaitHandle to shared

* Moved CancellationToken to shared

* _ remove from variable names

* Default change to Default(Token) and minor changes

* Fixing coreclr unix build

* moving semaphoreSlim to shared

* splitting safeWaitHandle to .windows and .unix

Commit migrated from https://github.com/dotnet/coreclr/commit/11c9d8590dc97b999e83c17dc992e886a6e9861b

src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj
src/coreclr/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs [deleted file]
src/coreclr/src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs
src/coreclr/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
src/libraries/System.Private.CoreLib/src/Interop/Windows/Kernel32/Interop.CloseHandle.cs
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs [moved from src/coreclr/src/System.Private.CoreLib/src/System/Threading/CancellationToken.cs with 89% similarity]
src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs [moved from src/coreclr/src/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs with 97% similarity]

index b6917cd..dbf4545 100644 (file)
     <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>
diff --git a/src/coreclr/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs b/src/coreclr/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
deleted file mode 100644 (file)
index 1141e6d..0000000
+++ /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);
-        }
-    }
-}
index a53ec79..d1a92a3 100644 (file)
@@ -276,8 +276,6 @@ namespace Microsoft.Win32
         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);
index d3c8113..7f41d25 100644 (file)
@@ -725,8 +725,6 @@ namespace System.Threading
             }
         }
 
-
-
         /// <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.
@@ -790,17 +788,17 @@ namespace System.Threading
         {
             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
@@ -815,10 +813,10 @@ namespace System.Threading
                     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();
index 96ed922..ff41f93 100644 (file)
@@ -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/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs
new file mode 100644 (file)
index 0000000..66f17f0
--- /dev/null
@@ -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/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
new file mode 100644 (file)
index 0000000..edb0cdf
--- /dev/null
@@ -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);
+        }
+    }
+}
index da36623..59a3074 100644 (file)
@@ -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" />
     <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" />
@@ -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<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>
@@ -136,7 +137,7 @@ namespace System.Threading
             Register(
                 s_actionToActionObjShunt,
                 callback ?? throw new ArgumentNullException(nameof(callback)),
-                useSyncContext: false,
+                useSynchronizationContext: false,
                 useExecutionContext: true);
 
         /// <summary>
@@ -189,7 +190,7 @@ namespace System.Threading
         /// 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 
@@ -222,19 +223,43 @@ namespace System.Threading
         // 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.
         }
 
@@ -305,9 +330,7 @@ namespace System.Threading
         public void ThrowIfCancellationRequested()
         {
             if (IsCancellationRequested)
-            {
                 ThrowOperationCanceledException();
-            }
         }
 
         // Throws an OCE; separated out to enable better inlining of ThrowIfCancellationRequested
@@ -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>
@@ -77,7 +65,7 @@ namespace System.Threading
         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 =
@@ -97,8 +85,9 @@ namespace System.Threading
                 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 @@ namespace System.Threading
         /// 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
@@ -267,7 +256,7 @@ namespace System.Threading
         /// 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)
         {
@@ -348,8 +337,8 @@ namespace System.Threading
             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 @@ namespace System.Threading
                         }
                     }
                 }
-
                 // 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 @@ namespace System.Threading
                         return false;
                     }
                 }
-
                 // ** the actual wait **
                 bool waitSuccessful = Monitor.Wait(m_lockObj, remainingWaitMilliseconds);
 
@@ -578,7 +565,7 @@ namespace System.Threading
         /// </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)
         {
@@ -599,7 +586,7 @@ namespace System.Threading
         /// </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)
         {
@@ -920,7 +907,7 @@ namespace System.Threading
             {
                 if (m_waitHandle != null)
                 {
-                    m_waitHandle.Close();
+                    m_waitHandle.Dispose();
                     m_waitHandle = null;
                 }
                 m_lockObj = null;
@@ -929,8 +916,6 @@ namespace System.Threading
             }
         }
 
-
-
         /// <summary>
         /// Private helper method to wake up waiters when a cancellationToken gets canceled.
         /// </summary>
@@ -956,7 +941,6 @@ namespace System.Threading
                 throw new ObjectDisposedException(null, SR.SemaphoreSlim_Disposed);
             }
         }
-
         #endregion
     }
 }