Fix comments
[mono.git] / mcs / class / corlib / System.Threading / SpinWait.cs
index a585c84726746babcf4ab2c596bbdbf5147aa235..136836746cc87e830c772e23c310ae1c822f0600 100644 (file)
@@ -1,4 +1,3 @@
-#if NET_4_0
 // SpinWait.cs
 //
 // Copyright (c) 2008 Jérémie "Garuma" Laval
 //
 //
 
+#if NET_4_0
 using System;
 
 namespace System.Threading
 {
-       
        public struct SpinWait
        {
                // The number of step until SpinOnce yield on multicore machine
                const           int  step = 10;
+               const           int  maxTime = 200;
                static readonly bool isSingleCpu = (Environment.ProcessorCount == 1);
-               
+
                int ntime;
-               
-               public void SpinOnce() 
+
+               public void SpinOnce ()
                {
-                       // On a single-CPU system, spinning does no good
+                       ntime += 1;
+
                        if (isSingleCpu) {
-                               Yield();
+                               // On a single-CPU system, spinning does no good
+                               Thread.Yield ();
                        } else {
-                               if (Interlocked.Increment(ref ntime) % step == 0) {
-                                       Yield();
-                               } else {
+                               if (ntime % step == 0)
+                                       Thread.Yield ();
+                               else
                                        // Multi-CPU system might be hyper-threaded, let other thread run
-                                       Thread.SpinWait(10);
-                               }
+                                       Thread.SpinWait (Math.Min (ntime, maxTime) << 1);
                        }
                }
-               
-               void Yield()
+
+               public static void SpinUntil (Func<bool> condition)
+               {
+                       SpinWait sw = new SpinWait ();
+                       while (!condition ())
+                               sw.SpinOnce ();
+               }
+
+               public static bool SpinUntil (Func<bool> condition, TimeSpan timeout)
+               {
+                       return SpinUntil (condition, (int)timeout.TotalMilliseconds);
+               }
+
+               public static bool SpinUntil (Func<bool> condition, int millisecondsTimeout)
                {
-                       // Replace sched_yield by Thread.Sleep(0) which does almost the same thing
-                       // (going back in kernel mode and yielding) but avoid the branching and unmanaged bridge
-                       Thread.Sleep(0);
+                       SpinWait sw = new SpinWait ();
+                       Watch watch = Watch.StartNew ();
+
+                       while (!condition ()) {
+                               if (watch.ElapsedMilliseconds > millisecondsTimeout)
+                                       return false;
+                               sw.SpinOnce ();
+                       }
+
+                       return true;
                }
-               
-               public void Reset()
+
+               public void Reset ()
                {
                        ntime = 0;
                }
-               
+
                public bool NextSpinWillYield {
                        get {
                                return isSingleCpu ? true : ntime % step == 0;
                        }
                }
-               
+
                public int Count {
                        get {
                                return ntime;