#if MONO using System; using System.Diagnostics; using System.Runtime; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Security.Permissions; using GSF; namespace System.Threading { /// Provides a mutual exclusion lock primitive where a thread trying to acquire the lock waits in a loop repeatedly checking until the lock becomes available. [DebuggerDisplay("IsHeld = {IsHeld}"), ComVisible(false)] [HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)] public struct SpinLock { #region [ Members ] // Fields private int m_lockState; #endregion #region [ Properties ] /// /// Gets whether the lock is currently held by any thread. /// /// true if the lock is currently held by any thread; otherwise false. public bool IsHeld { get { return this.m_lockState != 0; } } #endregion #region [ Methods ] /// /// Acquires the lock in a reliable manner, such that even if an exception occurs within the method call, can be examined reliably to determine whether the lock was acquired. /// /// True if the lock is acquired; otherwise, false. public void Enter(ref bool taken) { if (Interlocked.CompareExchange(ref m_lockState, 1, 0) != 0) { int count = 0; while (Interlocked.CompareExchange(ref m_lockState, 1, 0) != 0) { count++; if (Environment.ProcessorCount > 1 && count <= 5) Thread.SpinWait(25); else Thread.Sleep(0); } } taken = true; } /// /// Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within the method call, can be examined reliably to determine whether the lock was acquired. /// /// True if the lock is acquired; otherwise, false. public void TryEnter(ref bool lockTaken) { lockTaken = (Interlocked.CompareExchange(ref m_lockState, 1, 0) == 0); } /// /// Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within the method call, can be examined reliably to determine whether the lock was acquired. /// /// A that represents the number of milliseconds to wait, or a that represents -1 milliseconds to wait indefinitely. /// True if the lock is acquired; otherwise, false. must be initialized to false prior to calling this method. /// is a negative number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater than milliseconds. public void TryEnter(TimeSpan timeout, ref bool lockTaken) { long num = (long)timeout.TotalMilliseconds; if (num < -1L || num > 2147483647L) throw new ArgumentOutOfRangeException("timeout", timeout, "timeout value is out of range"); TryEnter((int)timeout.TotalMilliseconds, ref lockTaken); } /// /// Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within the method call, can be examined reliably to determine whether the lock was acquired. /// /// The number of milliseconds to wait, or (-1) to wait indefinitely. /// True if the lock is acquired; otherwise, false. must be initialized to false prior to calling this method. /// is a negative number other than -1, which represents an infinite time-out. public void TryEnter(int millisecondsTimeout, ref bool lockTaken) { if (millisecondsTimeout < -1) throw new ArgumentOutOfRangeException("millisecondsTimeout", "specified tiemout is a negative number other than -1."); if (millisecondsTimeout == -1) { Enter(ref lockTaken); return; } Ticks startTime = PrecisionTimer.UtcNow.Ticks; TryEnter(ref lockTaken); while (!lockTaken && (PrecisionTimer.UtcNow.Ticks - startTime).ToMilliseconds() < millisecondsTimeout) { Thread.Sleep(0); TryEnter(ref lockTaken); } } /// /// Releases the lock. /// public void Exit() { this.m_lockState = 0; } #endregion } } #endif