Moved Semaphore.cs and Semaphore.Windows.cs to shared (#18597)
authorAnirudh Agnihotry <anirudhagnihotry098@gmail.com>
Fri, 22 Jun 2018 01:39:23 +0000 (18:39 -0700)
committerGitHub <noreply@github.com>
Fri, 22 Jun 2018 01:39:23 +0000 (18:39 -0700)
* TryOpenexistingworker and createsemaphore moved to semaphore.windows.cs

* Common code moved to verifyCounts and CreateMutexCore and then moved to semaphore.windows.cs

* CreateSemaphore merged with CreateSemaphore core

* Moving interop functions from win32Native to inteop.kernel32

* Moving the files to shared

* Minor Formating

src/System.Private.CoreLib/System.Private.CoreLib.csproj
src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Constants.cs
src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Semaphore.cs [new file with mode: 0644]
src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs [new file with mode: 0644]
src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs [new file with mode: 0644]
src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs
src/System.Private.CoreLib/src/System/Threading/Semaphore.cs [deleted file]

index a97fa08..ccb3050 100644 (file)
     <Compile Include="$(BclSourcesRoot)\System\Threading\Interlocked.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Threading\Monitor.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Threading\Overlapped.cs" />
-    <Compile Include="$(BclSourcesRoot)\System\Threading\Semaphore.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Threading\Thread.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Threading\ThreadPool.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Threading\Timer.cs" />
index 8437f4b..59dace9 100644 (file)
@@ -9,5 +9,6 @@ internal static partial class Interop
         internal const int MAXIMUM_ALLOWED = 0x02000000;
         internal const int SYNCHRONIZE = 0x00100000;
         internal const int MUTEX_MODIFY_STATE = 0x00000001;
+        internal const int SEMAPHORE_MODIFY_STATE = 0x00000002;
     }
 }
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
new file mode 100644 (file)
index 0000000..6d1467b
--- /dev/null
@@ -0,0 +1,23 @@
+// 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 Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+    internal static partial class Kernel32
+    {
+        [DllImport(Interop.Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode)]
+        internal static extern SafeWaitHandle OpenSemaphore(uint desiredAccess, bool inheritHandle, string name);
+        
+        [DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode)]
+        internal static extern SafeWaitHandle CreateSemaphoreEx(IntPtr lpSecurityAttributes, int initialCount, int maximumCount, string name, uint flags, uint desiredAccess);
+
+        [DllImport(Interop.Libraries.Kernel32, SetLastError = true)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        internal static extern bool ReleaseSemaphore(SafeWaitHandle handle, int releaseCount, out int previousCount);
+    }
+}
index 7ee0321..eeef09b 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\Threading\NativeOverlapped.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Threading\ParameterizedThreadStart.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\SendOrPostCallback.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinWait.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.Errors.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FormatMessage.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Mutex.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Semaphore.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\Win32Marshal.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Mutex.Windows.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Semaphore.Windows.cs" />
   </ItemGroup>
   <ItemGroup Condition="$(TargetsUnix)">
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\Interop.Errors.cs" />
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs
new file mode 100644 (file)
index 0000000..f101564
--- /dev/null
@@ -0,0 +1,91 @@
+// 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 Microsoft.Win32.SafeHandles;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace System.Threading
+{
+    public sealed partial class Semaphore
+    {
+        private const uint AccessRights = (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.SEMAPHORE_MODIFY_STATE;
+
+        private Semaphore(SafeWaitHandle handle)
+        {
+            SafeWaitHandle = handle;
+        }
+
+        private void CreateSemaphoreCore(int initialCount, int maximumCount, string name, out bool createdNew)
+        {
+            Debug.Assert(initialCount >= 0);
+            Debug.Assert(maximumCount >= 1);
+            Debug.Assert(initialCount <= maximumCount);
+
+#if PLATFORM_UNIX
+            if (name != null)
+                throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
+#endif
+            SafeWaitHandle myHandle = Interop.Kernel32.CreateSemaphoreEx(IntPtr.Zero, initialCount, maximumCount, name, 0, AccessRights);
+
+            int errorCode = Marshal.GetLastWin32Error();
+            if (myHandle.IsInvalid)
+            {
+                if (name != null && name.Length != 0 && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+                    throw new WaitHandleCannotBeOpenedException(
+                        SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+
+                throw Win32Marshal.GetExceptionForLastWin32Error();
+            }
+            createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
+            this.SafeWaitHandle = myHandle;
+        }
+
+        private static OpenExistingResult OpenExistingWorker(string name, out Semaphore result)
+        {
+#if PLATFORM_WINDOWS
+            if (name == null)
+                throw new ArgumentNullException(nameof(name));
+            if (name.Length == 0)
+                throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
+
+            //Pass false to OpenSemaphore to prevent inheritedHandles
+            SafeWaitHandle myHandle = Interop.Kernel32.OpenSemaphore(AccessRights, false, name);
+
+            if (myHandle.IsInvalid)
+            {
+                result = null;
+                int errorCode = Marshal.GetLastWin32Error();
+
+                if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND || errorCode ==  Interop.Errors.ERROR_INVALID_NAME)
+                    return OpenExistingResult.NameNotFound;
+                if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND)
+                    return OpenExistingResult.PathNotFound;
+                if (name != null && name.Length != 0 && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+                    return OpenExistingResult.NameInvalid;
+                //this is for passed through NativeMethods Errors
+                throw Win32Marshal.GetExceptionForLastWin32Error();
+            }
+
+            result = new Semaphore(myHandle);
+            return OpenExistingResult.Success;
+#else
+            throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
+#endif
+        }
+
+        private int ReleaseCore(int releaseCount)
+        {
+            // If ReleaseSempahore returns false when the specified value would cause
+            // the semaphore's count to exceed the maximum count set when Semaphore was created
+            // Non-Zero return 
+            int 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
new file mode 100644 (file)
index 0000000..8e4ad76
--- /dev/null
@@ -0,0 +1,75 @@
+// 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 Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace System.Threading
+{
+    public sealed partial class Semaphore : WaitHandle
+    {
+        // creates a nameless semaphore object
+        // Win32 only takes maximum count of Int32.MaxValue
+        public Semaphore(int initialCount, int maximumCount) : this(initialCount, maximumCount, null) { }
+
+        public Semaphore(int initialCount, int maximumCount, string name)
+        {
+            VerifyCounts(initialCount, maximumCount);
+
+            bool createdNew;
+            CreateSemaphoreCore(initialCount, maximumCount, name, out createdNew);
+        }
+
+        public Semaphore(int initialCount, int maximumCount, string name, out bool createdNew)
+        {
+            VerifyCounts(initialCount, maximumCount);
+
+            CreateSemaphoreCore(initialCount, maximumCount, name, out createdNew);
+        }
+
+        private static void VerifyCounts(int initialCount, int maximumCount)
+        {
+            if (initialCount < 0)
+                throw new ArgumentOutOfRangeException(nameof(initialCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+            if (maximumCount < 1)
+                throw new ArgumentOutOfRangeException(nameof(maximumCount), SR.ArgumentOutOfRange_NeedPosNum);
+
+            if (initialCount > maximumCount)
+                throw new ArgumentException(SR.Argument_SemaphoreInitialMaximum);
+        }
+
+        public static Semaphore OpenExisting(string name)
+        {
+            Semaphore result;
+            switch (OpenExistingWorker(name, out result))
+            {
+                case OpenExistingResult.NameNotFound:
+                    throw new WaitHandleCannotBeOpenedException();
+                case OpenExistingResult.NameInvalid:
+                    throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+                case OpenExistingResult.PathNotFound:
+                    throw new IOException(SR.Format(SR.IO_PathNotFound_Path, name));
+                default:
+                    return result;
+            }
+        }
+
+        public static bool TryOpenExisting(string name, out Semaphore result) =>
+            OpenExistingWorker(name, out result) == OpenExistingResult.Success;
+
+        public int Release() => ReleaseCore(1);
+
+        // increase the count on a semaphore, returns previous count
+        public int Release(int releaseCount)
+        {
+            if (releaseCount < 1)
+                throw new ArgumentOutOfRangeException(nameof(releaseCount), SR.ArgumentOutOfRange_NeedNonNegNum);
+
+            return ReleaseCore(releaseCount);
+        }
+    }
+}
index 61dd2b3..dcd4345 100644 (file)
@@ -165,7 +165,6 @@ namespace Microsoft.Win32
 
         // Note that you may need to specify the SYNCHRONIZE bit as well
         // to be able to open a synchronization primitive.
-        internal const int SEMAPHORE_MODIFY_STATE = 0x00000002;
         internal const int EVENT_MODIFY_STATE = 0x00000002;
         internal const int MUTEX_MODIFY_STATE = 0x00000001;
 
@@ -312,16 +311,6 @@ namespace Microsoft.Win32
         [DllImport(Interop.Libraries.Kernel32, SetLastError = true)]
         internal static extern unsafe int WriteFile(SafeFileHandle handle, byte* bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero);
 
-        [DllImport(Interop.Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
-        internal static extern SafeWaitHandle CreateSemaphoreEx(SECURITY_ATTRIBUTES lpSecurityAttributes, int initialCount, int maximumCount, string name, uint flags, uint desiredAccess);
-
-        [DllImport(Interop.Libraries.Kernel32, SetLastError = true)]
-        [return: MarshalAs(UnmanagedType.Bool)]
-        internal static extern bool ReleaseSemaphore(SafeWaitHandle handle, int releaseCount, out int previousCount);
-
-        [DllImport(Interop.Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
-        internal static extern SafeWaitHandle OpenSemaphore(uint desiredAccess, bool inheritHandle, string name);
-
         internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);  // WinBase.h
 
         // Note, these are #defines used to extract handles, and are NOT handles.
diff --git a/src/System.Private.CoreLib/src/System/Threading/Semaphore.cs b/src/System.Private.CoreLib/src/System/Threading/Semaphore.cs
deleted file mode 100644 (file)
index 2853485..0000000
+++ /dev/null
@@ -1,186 +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.
-
-using Microsoft.Win32;
-using Microsoft.Win32.SafeHandles;
-using System.Diagnostics;
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Security;
-
-namespace System.Threading
-{
-    public sealed partial class Semaphore : WaitHandle
-    {
-        private const uint AccessRights =
-            (uint)Win32Native.MAXIMUM_ALLOWED | Win32Native.SYNCHRONIZE | Win32Native.SEMAPHORE_MODIFY_STATE;
-
-        public Semaphore(int initialCount, int maximumCount) : this(initialCount, maximumCount, null) { }
-
-        public Semaphore(int initialCount, int maximumCount, string name)
-        {
-            if (initialCount < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(initialCount), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-
-            if (maximumCount < 1)
-            {
-                throw new ArgumentOutOfRangeException(nameof(maximumCount), SR.ArgumentOutOfRange_NeedPosNum);
-            }
-
-            if (initialCount > maximumCount)
-            {
-                throw new ArgumentException(SR.Argument_SemaphoreInitialMaximum);
-            }
-
-            SafeWaitHandle myHandle = CreateSemaphore(initialCount, maximumCount, name);
-
-            if (myHandle.IsInvalid)
-            {
-                int errorCode = Marshal.GetLastWin32Error();
-
-                if (null != name && 0 != name.Length && Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
-                    throw new WaitHandleCannotBeOpenedException(
-                        SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
-
-                throw Win32Marshal.GetExceptionForLastWin32Error();
-            }
-            this.SafeWaitHandle = myHandle;
-        }
-
-        public Semaphore(int initialCount, int maximumCount, string name, out bool createdNew)
-        {
-            if (initialCount < 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(initialCount), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-
-            if (maximumCount < 1)
-            {
-                throw new ArgumentOutOfRangeException(nameof(maximumCount), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-
-            if (initialCount > maximumCount)
-            {
-                throw new ArgumentException(SR.Argument_SemaphoreInitialMaximum);
-            }
-
-            SafeWaitHandle myHandle = CreateSemaphore(initialCount, maximumCount, name);
-
-            int errorCode = Marshal.GetLastWin32Error();
-            if (myHandle.IsInvalid)
-            {
-                if (null != name && 0 != name.Length && Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
-                    throw new WaitHandleCannotBeOpenedException(
-                        SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
-                throw Win32Marshal.GetExceptionForLastWin32Error();
-            }
-            createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
-            this.SafeWaitHandle = myHandle;
-        }
-
-        private Semaphore(SafeWaitHandle handle)
-        {
-            this.SafeWaitHandle = handle;
-        }
-
-        private static SafeWaitHandle CreateSemaphore(int initialCount, int maximumCount, string name)
-        {
-#if !PLATFORM_WINDOWS
-            if (name != null)
-            {
-                throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
-            }
-#endif
-
-            Debug.Assert(initialCount >= 0);
-            Debug.Assert(maximumCount >= 1);
-            Debug.Assert(initialCount <= maximumCount);
-
-            return Win32Native.CreateSemaphoreEx(null, initialCount, maximumCount, name, 0, AccessRights);
-        }
-
-        public static Semaphore OpenExisting(string name)
-        {
-            Semaphore result;
-            switch (OpenExistingWorker(name, out result))
-            {
-                case OpenExistingResult.NameNotFound:
-                    throw new WaitHandleCannotBeOpenedException();
-                case OpenExistingResult.NameInvalid:
-                    throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
-                case OpenExistingResult.PathNotFound:
-                    throw new IOException(Interop.Kernel32.GetMessage(Interop.Errors.ERROR_PATH_NOT_FOUND));
-                default:
-                    return result;
-            }
-        }
-
-        public static bool TryOpenExisting(string name, out Semaphore result)
-        {
-            return OpenExistingWorker(name, out result) == OpenExistingResult.Success;
-        }
-
-        private static OpenExistingResult OpenExistingWorker(string name, out Semaphore result)
-        {
-#if PLATFORM_WINDOWS
-            if (name == null)
-                throw new ArgumentNullException(nameof(name));
-            if (name.Length == 0)
-                throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
-
-            //Pass false to OpenSemaphore to prevent inheritedHandles
-            SafeWaitHandle myHandle = Win32Native.OpenSemaphore(AccessRights, false, name);
-
-            if (myHandle.IsInvalid)
-            {
-                result = null;
-
-                int errorCode = Marshal.GetLastWin32Error();
-
-                if (Interop.Errors.ERROR_FILE_NOT_FOUND == errorCode || Interop.Errors.ERROR_INVALID_NAME == errorCode)
-                    return OpenExistingResult.NameNotFound;
-                if (Interop.Errors.ERROR_PATH_NOT_FOUND == errorCode)
-                    return OpenExistingResult.PathNotFound;
-                if (null != name && 0 != name.Length && Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
-                    return OpenExistingResult.NameInvalid;
-                //this is for passed through NativeMethods Errors
-                throw Win32Marshal.GetExceptionForLastWin32Error();
-            }
-
-            result = new Semaphore(myHandle);
-            return OpenExistingResult.Success;
-#else
-            throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
-#endif
-        }
-
-        public int Release()
-        {
-            return Release(1);
-        }
-
-        // increase the count on a semaphore, returns previous count
-        public int Release(int releaseCount)
-        {
-            if (releaseCount < 1)
-            {
-                throw new ArgumentOutOfRangeException(nameof(releaseCount), SR.ArgumentOutOfRange_NeedNonNegNum);
-            }
-
-            //If ReleaseSempahore returns false when the specified value would cause
-            //   the semaphore's count to exceed the maximum count set when Semaphore was created
-            //Non-Zero return 
-
-            int previousCount;
-            if (!Win32Native.ReleaseSemaphore(SafeWaitHandle, releaseCount, out previousCount))
-            {
-                throw new SemaphoreFullException();
-            }
-
-            return previousCount;
-        }
-    }
-}