<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" />
// 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;
[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.
+++ /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 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;
- }
- }
-}
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;
}
}
--- /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 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);
+ }
+}
<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" />
--- /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 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;
+ }
+ }
+}
--- /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 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);
+ }
+ }
+}