Xamarin Public Jenkins (auto-signing) ef583813eb Imported Upstream version 6.4.0.137
Former-commit-id: 943baa9f16a098c33e129777827f3a9d20da00d6
2019-07-26 19:53:28 +00:00

99 lines
3.5 KiB
C#

using System.Runtime.CompilerServices;
using Microsoft.Win32.SafeHandles;
using System.IO;
namespace System.Threading
{
partial class Semaphore
{
const int MAX_PATH = 260;
Semaphore (SafeWaitHandle handle) => this.SafeWaitHandle = handle;
int ReleaseCore (int releaseCount)
{
if (!ReleaseSemaphore_internal (SafeWaitHandle.DangerousGetHandle (), releaseCount, out int previousCount))
throw new SemaphoreFullException ();
return previousCount;
}
static OpenExistingResult OpenExistingWorker (string name, out Semaphore result)
{
if (name == null)
throw new ArgumentNullException (nameof (name));
if (name.Length == 0)
throw new ArgumentException (SR.Argument_StringZeroLength, nameof (name));
if (name.Length > MAX_PATH)
throw new ArgumentException (SR.Argument_WaitHandleNameTooLong);
var myHandle = new SafeWaitHandle (OpenSemaphore_internal (name,
/*SemaphoreRights.Modify | SemaphoreRights.Synchronize*/ 0x000002 | 0x100000,
out MonoIOError errorCode), true);
if (myHandle.IsInvalid) {
result = null;
switch (errorCode) {
case MonoIOError.ERROR_FILE_NOT_FOUND:
case MonoIOError.ERROR_INVALID_NAME:
return OpenExistingResult.NameNotFound;
case MonoIOError.ERROR_PATH_NOT_FOUND:
return OpenExistingResult.PathNotFound;
case MonoIOError.ERROR_INVALID_HANDLE when !string.IsNullOrEmpty (name):
return OpenExistingResult.NameInvalid;
default:
//this is for passed through NativeMethods Errors
throw new IOException ($"Unknown Error '{errorCode}'");
}
}
result = new Semaphore (myHandle);
return OpenExistingResult.Success;
}
void CreateSemaphoreCore (int initialCount, int maximumCount, string name, out bool createdNew)
{
if (name?.Length > MAX_PATH)
throw new ArgumentException (SR.Argument_WaitHandleNameTooLong);
var myHandle = new SafeWaitHandle (CreateSemaphore_internal (initialCount, maximumCount, name, out MonoIOError errorCode), true);
if (myHandle.IsInvalid) {
if (errorCode == MonoIOError.ERROR_INVALID_HANDLE && !string.IsNullOrEmpty (name))
throw new WaitHandleCannotBeOpenedException (SR.Format (SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
throw new IOException ($"Unknown Error '{errorCode}'");
}
this.SafeWaitHandle = myHandle;
createdNew = errorCode != MonoIOError.ERROR_ALREADY_EXISTS;
}
unsafe static IntPtr CreateSemaphore_internal (int initialCount, int maximumCount, string name, out MonoIOError errorCode)
{
// FIXME Check for embedded nuls in name.
fixed (char *fixed_name = name)
return CreateSemaphore_icall (initialCount, maximumCount,
fixed_name, name?.Length ?? 0, out errorCode);
}
unsafe static IntPtr OpenSemaphore_internal (string name, int rights, out MonoIOError errorCode)
{
// FIXME Check for embedded nuls in name.
fixed (char *fixed_name = name)
return OpenSemaphore_icall (fixed_name, name?.Length ?? 0, rights, out errorCode);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
unsafe static extern IntPtr CreateSemaphore_icall (int initialCount, int maximumCount, char* name, int nameLength, out MonoIOError errorCode);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
unsafe static extern IntPtr OpenSemaphore_icall (char* name, int nameLength, int rights, out MonoIOError errorCode);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern bool ReleaseSemaphore_internal (IntPtr handle, int releaseCount, out int previousCount);
}
}