Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/rx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Rx.NET/System.Reactive.Core/Reactive/Internal/Semaphore.Xna.cs')
-rw-r--r--Rx.NET/System.Reactive.Core/Reactive/Internal/Semaphore.Xna.cs143
1 files changed, 143 insertions, 0 deletions
diff --git a/Rx.NET/System.Reactive.Core/Reactive/Internal/Semaphore.Xna.cs b/Rx.NET/System.Reactive.Core/Reactive/Internal/Semaphore.Xna.cs
new file mode 100644
index 0000000..847c14d
--- /dev/null
+++ b/Rx.NET/System.Reactive.Core/Reactive/Internal/Semaphore.Xna.cs
@@ -0,0 +1,143 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license 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 \ No newline at end of file