#if MONO using System; using System.Runtime; using System.Security.Permissions; namespace System.Threading { /// Provides support for spin-based waiting. [__DynamicallyInvokable] [HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)] public struct SpinWait { internal const int YIELD_THRESHOLD = 10; internal const int SLEEP_0_EVERY_HOW_MANY_TIMES = 5; internal const int SLEEP_1_EVERY_HOW_MANY_TIMES = 20; private int m_count; /// Gets the number of times has been called on this instance. /// Returns an integer that represents the number of times has been called on this instance. [__DynamicallyInvokable] public int Count { [__DynamicallyInvokable] get { return this.m_count; } } /// Gets whether the next call to will yield the processor, triggering a forced context switch. /// Whether the next call to will yield the processor, triggering a forced context switch. [__DynamicallyInvokable] public bool NextSpinWillYield { [__DynamicallyInvokable] get { return this.m_count > 10 || PlatformHelper.IsSingleProcessor; } } /// Performs a single spin. [__DynamicallyInvokable] public void SpinOnce() { if (this.NextSpinWillYield) { //CdsSyncEtwBCLProvider.Log.SpinWait_NextSpinWillYield(); int num = (this.m_count >= 10) ? (this.m_count - 10) : this.m_count; if (num % 20 == 19) { Thread.Sleep(1); } else { Thread.Sleep(0); //if (num % 5 == 4) //{ // Thread.Sleep(0); //} //else //{ // Thread.Sleep(0); //} } } else { Thread.SpinWait(4 << this.m_count); } this.m_count = ((this.m_count == 2147483647) ? 10 : (this.m_count + 1)); } /// Resets the spin counter. [__DynamicallyInvokable] public void Reset() { this.m_count = 0; } /// Spins until the specified condition is satisfied. /// A delegate to be executed over and over until it returns true. /// The argument is null. [__DynamicallyInvokable] public static void SpinUntil(Func condition) { SpinWait.SpinUntil(condition, -1); } /// Spins until the specified condition is satisfied or until the specified timeout is expired. /// True if the condition is satisfied within the timeout; otherwise, false /// A delegate to be executed over and over until it returns true. /// A that represents the number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. /// The argument is null. /// /// is a negative number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater than . [__DynamicallyInvokable] public static bool SpinUntil(Func condition, TimeSpan timeout) { long num = (long)timeout.TotalMilliseconds; if (num < -1L || num > 2147483647L) { throw new ArgumentOutOfRangeException("timeout", timeout, "SpinWait_SpinUntil_TimeoutWrong"); } return SpinWait.SpinUntil(condition, (int)timeout.TotalMilliseconds); } /// Spins until the specified condition is satisfied or until the specified timeout is expired. /// True if the condition is satisfied within the timeout; otherwise, false /// A delegate to be executed over and over until it returns true. /// The number of milliseconds to wait, or (-1) to wait indefinitely. /// The argument is null. /// /// is a negative number other than -1, which represents an infinite time-out. [__DynamicallyInvokable] public static bool SpinUntil(Func condition, int millisecondsTimeout) { if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeout", millisecondsTimeout, "SpinWait_SpinUntil_TimeoutWrong"); } if (condition == null) { throw new ArgumentNullException("condition", "SpinWait_SpinUntil_ArgumentNull"); } uint num = 0u; if (millisecondsTimeout != 0 && millisecondsTimeout != -1) { num = TimeoutHelper.GetTime(); } SpinWait spinWait = default(SpinWait); while (!condition()) { if (millisecondsTimeout == 0) { return false; } spinWait.SpinOnce(); if (millisecondsTimeout != -1 && spinWait.NextSpinWillYield && (long)millisecondsTimeout <= (long)((ulong)(TimeoutHelper.GetTime() - num))) { return false; } } return true; } } } #endif