|
|
@@ -1,145 +0,0 @@
|
|
|
-// Licensed to the .NET Foundation under one or more agreements.
|
|
|
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
|
|
-// See the LICENSE file in the project root for more information.
|
|
|
-
|
|
|
-#if NO_SEMAPHORE && (XNA || NETCF)
|
|
|
-using System;
|
|
|
-using System.Collections.Generic;
|
|
|
-using System.Threading;
|
|
|
-
|
|
|
-namespace System.Reactive.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 readonly int m_maximumCount;
|
|
|
- private readonly object m_lockObject;
|
|
|
- private bool m_disposed;
|
|
|
- private readonly List<ManualResetEvent> m_waiting;
|
|
|
-
|
|
|
- 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_waiting = new List<ManualResetEvent>();
|
|
|
- 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);
|
|
|
- var toBeReleased = new List<ManualResetEvent>();
|
|
|
- lock (m_lockObject)
|
|
|
- {
|
|
|
- oldCount = m_currentCount;
|
|
|
- if (releaseCount + m_currentCount > m_maximumCount)
|
|
|
- {
|
|
|
- throw new ArgumentOutOfRangeException("releaseCount", "Amount of releases would overflow maximum");
|
|
|
- }
|
|
|
-
|
|
|
- var waiting = m_waiting.ToArray();
|
|
|
- var left = Math.Max(0, releaseCount - waiting.Length);
|
|
|
- for (var i = 0; i < releaseCount && i < m_waiting.Count; i++)
|
|
|
- {
|
|
|
- toBeReleased.Add(waiting[i]);
|
|
|
- m_waiting.RemoveAt(0);
|
|
|
- }
|
|
|
- m_currentCount += left;
|
|
|
- }
|
|
|
- foreach(var release in toBeReleased)
|
|
|
- {
|
|
|
- release.Set();
|
|
|
- }
|
|
|
- return oldCount;
|
|
|
- }
|
|
|
-
|
|
|
- public bool WaitOne()
|
|
|
- {
|
|
|
- return WaitOne(Timeout.Infinite);
|
|
|
- }
|
|
|
-
|
|
|
- public bool WaitOne(int millisecondsTimeout)
|
|
|
- {
|
|
|
- if (m_disposed)
|
|
|
- {
|
|
|
- throw new ObjectDisposedException("Semaphore");
|
|
|
- }
|
|
|
-
|
|
|
- var manualResetEvent = default(ManualResetEvent);
|
|
|
-
|
|
|
- lock (m_lockObject)
|
|
|
- {
|
|
|
- if (m_currentCount == 0)
|
|
|
- {
|
|
|
- manualResetEvent = new ManualResetEvent(false);
|
|
|
- m_waiting.Add(manualResetEvent);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- m_currentCount--;
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-#if XNA_31_ZUNE || NETCF35
|
|
|
- if (!manualResetEvent.WaitOne(millisecondsTimeout, false))
|
|
|
-#else
|
|
|
- if (!manualResetEvent.WaitOne(millisecondsTimeout))
|
|
|
-#endif
|
|
|
- {
|
|
|
- lock(m_lockObject)
|
|
|
- {
|
|
|
- m_waiting.Remove(manualResetEvent);
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
- 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;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-#endif
|