Implement a Semaphore

Test:

        [TestMethod]
public void TestSemaphore()
{
var semaphore = new Semaphore(2);
semaphore.Enter();
semaphore.Enter();

VerifyEnterRelease(semaphore);
VerifyEnterRelease(semaphore);

semaphore.Release();
semaphore.Release();

semaphore.Enter();
semaphore.Enter();

VerifyEnterRelease(semaphore);
VerifyEnterRelease(semaphore);
}

private static void VerifyEnterRelease(Semaphore semaphore)
{
Task task1 = Task.Factory.StartNew(semaphore.Enter);

bool taskCompletedBeforeRelease = task1.Wait(TimeSpan.FromSeconds(5));
Assert.IsFalse(taskCompletedBeforeRelease, "Semaphore shouldn't release 3rd entering thread");

semaphore.Release();

bool taskCompletedAfterRelease = task1.Wait(TimeSpan.FromSeconds(15));
Assert.IsTrue(taskCompletedAfterRelease, "Semaphore was not released");
}



Solution:

    public class Semaphore
{
private int counter;
readonly AutoResetEvent autoResetEvent = new AutoResetEvent(false);
private readonly int max;

public Semaphore(int max)
{
this.max = max;
}

public void Enter()
{
int newCounter = Interlocked.Increment(ref counter);
if (newCounter > max)
{
autoResetEvent.WaitOne();
}
}

public void Release()
{
int newCounter = Interlocked.Decrement(ref counter);
if (newCounter >= max)
{
autoResetEvent.Set();
}
}
}

Comments