diff options
Diffstat (limited to 'Rx.NET/Tests.System.Reactive/Semaphore.cs')
-rw-r--r-- | Rx.NET/Tests.System.Reactive/Semaphore.cs | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/Rx.NET/Tests.System.Reactive/Semaphore.cs b/Rx.NET/Tests.System.Reactive/Semaphore.cs new file mode 100644 index 0000000..471672c --- /dev/null +++ b/Rx.NET/Tests.System.Reactive/Semaphore.cs @@ -0,0 +1,116 @@ +// 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
\ No newline at end of file |