using System;
using System.Runtime.InteropServices;
namespace System.Threading
{
public sealed class Semaphore : IDisposable
{
public Semaphore(int initCount, int maxCount, string name)
{
this.maxCount = maxCount;
nativeHandle = CreateSemaphore(0, initCount, maxCount, name);
if (nativeHandle == IntPtr.Zero)
throw new Exception("CreateSemaphore failed");
int gle = Marshal.GetLastWin32Error();
openedObject = (gle != 0);
}
public Semaphore(int initCount, int maxCount)
: this(initCount, maxCount, null)
{
}
public int Release()
{
return Release(1);
}
public int Release(int count)
{
int prevCount = 0;
ReleaseSemaphore(nativeHandle, count, out prevCount);
return prevCount;
}
int maxCount = 0;
protected IntPtr nativeHandle = IntPtr.Zero;
protected bool openedObject = false;
const int INFINITE = -1;
public int MaxCount
{
get { return maxCount; }
}
public bool WasCreated
{
get
{
return !openedObject;
}
}
~Semaphore()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (nativeHandle != IntPtr.Zero)
{
CloseHandle(nativeHandle);
nativeHandle = IntPtr.Zero;
}
}
public bool WaitOne(int timeout)
{
return 0 == WaitForSingleObject(nativeHandle, timeout);
}
public bool WaitOne()
{
return WaitOne(INFINITE);
}
[DllImport("CoreDLL", SetLastError = true)]
protected extern static int WaitForSingleObject(IntPtr hEvent, int timeout);
[DllImport("coredll.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
protected static extern bool CloseHandle(IntPtr hObject);
[DllImport("CoreDLL", SetLastError = true)]
protected static extern IntPtr CreateSemaphore(
int alwaysZero,
int lInitialCount,
int lMaximumCount,
string lpName
);
[DllImport("CoreDLL", SetLastError = true)]
protected static extern int ReleaseSemaphore(
IntPtr hSemaphore,
int lReleaseCount,
out int lpPreviousCount
);
}
}