-#if NET_4_0
// ManuelResetEventSlim.cs
//
// Copyright (c) 2008 Jérémie "Garuma" Laval
//
//
+#if NET_4_0 || MOBILE
+
using System;
-using System.Diagnostics;
namespace System.Threading
-{
+{
+ [System.Diagnostics.DebuggerDisplayAttribute ("Set = {IsSet}")]
public class ManualResetEventSlim : IDisposable
{
- const int defaultSpinCount = 20;
const int isSet = 1;
const int isNotSet = 0;
- readonly int spinCount;
- readonly SpinWait sw = new SpinWait ();
+ const int defaultSpinCount = 100;
int state;
-
- //bool isDisposed;
-
- public ManualResetEventSlim () : this(false, 20)
+ readonly int spinCount;
+
+ ManualResetEvent handle;
+
+ readonly static Watch sw = Watch.StartNew ();
+
+ public ManualResetEventSlim () : this (false, defaultSpinCount)
{
}
-
- public ManualResetEventSlim (bool initState) : this (initState, 20)
+
+ public ManualResetEventSlim (bool initialState) : this (initialState, defaultSpinCount)
{
}
-
- public ManualResetEventSlim (bool initState, int spinCount)
+
+ public ManualResetEventSlim (bool initialState, int spinCount)
{
- this.state = initState ? isSet : isNotSet;
+ if (spinCount < 0)
+ throw new ArgumentOutOfRangeException ("spinCount is less than 0", "spinCount");
+
+ this.state = initialState ? isSet : isNotSet;
this.spinCount = spinCount;
}
-
- /*~ManualResetEventSlim()
- {
- Dispose(false);
- }*/
-
+
public bool IsSet {
get {
return state == isSet;
return spinCount;
}
}
-
+
public void Reset ()
{
- Thread.VolatileWrite (ref state, isNotSet);
+ state = isNotSet;
+ if (handle != null)
+ handle.Reset ();
}
-
+
public void Set ()
{
- // Make sure that even is state was cached by a CPU the new value is correctly propagated
- Thread.VolatileWrite (ref state, isSet);
+ state = isSet;
+ if (handle != null)
+ handle.Set ();
}
-
+
public void Wait ()
{
- // First spin
- for (int i = 0; i < spinCount && state == isNotSet; i++)
- sw.SpinOnce ();
-
- // Then, fallback to classic Sleep's yielding
- while (state == isNotSet)
- Thread.Sleep (0);
- }
-
+ Wait (CancellationToken.None);
+ }
+
public bool Wait (int millisecondsTimeout)
+ {
+ return Wait (millisecondsTimeout, CancellationToken.None);
+ }
+
+ public bool Wait (TimeSpan timeout)
+ {
+ return Wait ((int)timeout.TotalMilliseconds, CancellationToken.None);
+ }
+
+ public void Wait (CancellationToken cancellationToken)
+ {
+ Wait (-1, cancellationToken);
+ }
+
+ public bool Wait (int millisecondsTimeout, CancellationToken cancellationToken)
{
if (millisecondsTimeout < -1)
throw new ArgumentOutOfRangeException ("millisecondsTimeout",
"millisecondsTimeout is a negative number other than -1");
-
- if (millisecondsTimeout == -1) {
- Wait ();
- return true;
- }
-
- Watch s = Watch.StartNew ();
-
- // First spin
- for (int i = 0; i < spinCount && state == isNotSet; i++) {
- if (s.ElapsedMilliseconds >= millisecondsTimeout)
- return false;
-
- sw.SpinOnce ();
- }
-
- // Then, fallback to classic Sleep's yielding
+
+ long start = millisecondsTimeout == -1 ? 0 : sw.ElapsedMilliseconds;
+ SpinWait wait = new SpinWait ();
+
while (state == isNotSet) {
- if (s.ElapsedMilliseconds >= millisecondsTimeout)
+ cancellationToken.ThrowIfCancellationRequested ();
+
+ if (millisecondsTimeout > -1 && (sw.ElapsedMilliseconds - start) > millisecondsTimeout)
return false;
-
- Thread.Sleep (0);
+
+ if (wait.Count < spinCount) {
+ wait.SpinOnce ();
+ } else {
+ int waitTime = millisecondsTimeout == -1 ? -1 : Math.Max (millisecondsTimeout - (int)(sw.ElapsedMilliseconds - start) , 1);
+ WaitHandle handle = WaitHandle;
+ if (state == isSet)
+ return true;
+ if (WaitHandle.WaitAny (new[] { handle, cancellationToken.WaitHandle }, waitTime, false) == 0)
+ return true;
+ }
}
-
+
return true;
}
-
- public bool Wait (TimeSpan ts)
+
+ public bool Wait (TimeSpan timeout, CancellationToken cancellationToken)
{
- return Wait ((int)ts.TotalMilliseconds);
+ return Wait ((int)timeout.TotalMilliseconds, cancellationToken);
}
-
+
public WaitHandle WaitHandle {
get {
- // FIXME
- return null;
+ if (handle != null) {
+ if (state == isSet)
+ handle.Set ();
+
+ return handle;
+ }
+
+ var result = LazyInitializer.EnsureInitialized (ref handle,
+ () => new ManualResetEvent (state == isSet ? true : false));
+ if (state == isSet)
+ result.Set ();
+
+ return result;
}
}
-
- #region IDisposable implementation
-
+
+ #region IDisposable implementation
public void Dispose ()
{
- //Dispose(true);
+ Dispose(true);
}
-
- /*protected virtual void Dispose(bool managedRes)
+
+ protected virtual void Dispose (bool disposing)
{
-
- }*/
- #endregion
-
+
+ }
+ #endregion
+
}
}
#endif