a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
116 lines
3.3 KiB
C#
116 lines
3.3 KiB
C#
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
#if SILVERLIGHT
|
|
using System;
|
|
|
|
namespace System.Threading
|
|
{
|
|
//Monitor based implementation of Semaphore
|
|
//that mimicks the .NET Semaphore class (System.Threading.Semaphore)
|
|
|
|
internal sealed class Semaphore : IDisposable
|
|
{
|
|
private int m_currentCount;
|
|
private int m_maximumCount;
|
|
private object m_lockObject;
|
|
private bool m_disposed;
|
|
|
|
public Semaphore(int initialCount, int maximumCount)
|
|
{
|
|
if (initialCount < 0)
|
|
{
|
|
throw new ArgumentOutOfRangeException("initialCount", "Non-negative number required.");
|
|
}
|
|
if (maximumCount < 1)
|
|
{
|
|
throw new ArgumentOutOfRangeException("maximumCount", "Positive number required.");
|
|
}
|
|
if (initialCount > maximumCount)
|
|
{
|
|
throw new ArgumentException("Initial count must be smaller than maximum");
|
|
}
|
|
|
|
m_currentCount = initialCount;
|
|
m_maximumCount = maximumCount;
|
|
m_lockObject = new object();
|
|
}
|
|
|
|
public int Release()
|
|
{
|
|
return this.Release(1);
|
|
}
|
|
|
|
public int Release(int releaseCount)
|
|
{
|
|
if (releaseCount < 1)
|
|
{
|
|
throw new ArgumentOutOfRangeException("releaseCount", "Positive number required.");
|
|
}
|
|
if (m_disposed)
|
|
{
|
|
throw new ObjectDisposedException("Semaphore");
|
|
}
|
|
|
|
var oldCount = default(int);
|
|
lock (m_lockObject)
|
|
{
|
|
oldCount = m_currentCount;
|
|
if (releaseCount + m_currentCount > m_maximumCount)
|
|
{
|
|
throw new ArgumentOutOfRangeException("releaseCount", "Amount of releases would overflow maximum");
|
|
}
|
|
m_currentCount += releaseCount;
|
|
//PulseAll makes sure all waiting threads get queued for acquiring the lock
|
|
//Pulse would only queue one thread.
|
|
|
|
Monitor.PulseAll(m_lockObject);
|
|
}
|
|
return oldCount;
|
|
}
|
|
|
|
public bool WaitOne()
|
|
{
|
|
return WaitOne(Timeout.Infinite);
|
|
}
|
|
|
|
public bool WaitOne(int millisecondsTimeout)
|
|
{
|
|
if (m_disposed)
|
|
{
|
|
throw new ObjectDisposedException("Semaphore");
|
|
}
|
|
|
|
lock (m_lockObject)
|
|
{
|
|
while (m_currentCount == 0)
|
|
{
|
|
if (!Monitor.Wait(m_lockObject, millisecondsTimeout))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
m_currentCount--;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public bool WaitOne(TimeSpan timeout)
|
|
{
|
|
return WaitOne((int)timeout.TotalMilliseconds);
|
|
}
|
|
|
|
public void Close()
|
|
{
|
|
Dispose();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
//the .NET CLR semaphore does not release waits upon dispose
|
|
//so we don't do that either.
|
|
m_disposed = true;
|
|
m_lockObject = null;
|
|
}
|
|
}
|
|
}
|
|
#endif |