You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2983 lines
103 KiB
2983 lines
103 KiB
// Needed for NET40 |
|
#if !NET_4_6 |
|
using System; |
|
using System.Threading; |
|
|
|
namespace LinqInternal.Threading |
|
{ |
|
internal static partial class ThreadingHelper |
|
{ |
|
public static void SpinWaitSet(ref int check, int value, int comparand) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
if (Interlocked.CompareExchange(ref check, value, comparand) != comparand) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
} |
|
|
|
public static void SpinWaitSet(ref int check, int value, int comparand, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Interlocked.CompareExchange(ref check, value, comparand) != comparand) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
} |
|
|
|
public static bool SpinWaitSet(ref int check, int value, int comparand, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
SpinWaitSet(ref check, value, comparand); |
|
return true; |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
if (Interlocked.CompareExchange(ref check, value, comparand) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSet(ref int check, int value, int comparand, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
SpinWaitSet(ref check, value, comparand, cancellationToken); |
|
return true; |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Interlocked.CompareExchange(ref check, value, comparand) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSet(ref int check, int value, int comparand, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
if (Interlocked.CompareExchange(ref check, value, comparand) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSet(ref int check, int value, int comparand, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Interlocked.CompareExchange(ref check, value, comparand) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSet(ref int check, int value, int comparand, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
if (Interlocked.CompareExchange(ref check, value, comparand) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSet(ref int check, int value, int comparand, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Interlocked.CompareExchange(ref check, value, comparand) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static void SpinWaitUntil(ref int check, int comparand) |
|
{ |
|
var spinWait = new SpinWait(); |
|
while (Volatile.Read(ref check) != comparand) |
|
{ |
|
spinWait.SpinOnce(); |
|
} |
|
} |
|
|
|
public static void SpinWaitUntil(ref int check, int comparand, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) == comparand) |
|
{ |
|
return; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitUntil(ref int check, int comparand, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
SpinWaitUntil(ref check, comparand); |
|
return true; |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
if (Volatile.Read(ref check) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitUntil(ref int check, int comparand, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
SpinWaitUntil(ref check, comparand, cancellationToken); |
|
return true; |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitUntil(ref int check, int comparand, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
if (Volatile.Read(ref check) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitUntil(ref int check, int comparand, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitUntil(ref int check, int comparand, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
if (Volatile.Read(ref check) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitUntil(ref int check, int comparand, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) == comparand) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static void SpinWaitUntil(Func<bool> verification) |
|
{ |
|
var spinWait = new SpinWait(); |
|
while (!verification.Invoke()) |
|
{ |
|
spinWait.SpinOnce(); |
|
} |
|
} |
|
|
|
public static void SpinWaitUntil(Func<bool> verification, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (verification.Invoke()) |
|
{ |
|
return; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitUntil(Func<bool> verification, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
SpinWaitUntil(verification); |
|
return true; |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
if (verification.Invoke()) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitUntil(Func<bool> verification, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
SpinWaitUntil(verification, cancellationToken); |
|
return true; |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (verification.Invoke()) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitUntil(Func<bool> verification, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
if (verification.Invoke()) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitUntil(Func<bool> verification, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (verification.Invoke()) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitUntil(Func<bool> verification, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
if (verification.Invoke()) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitUntil(Func<bool> verification, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (verification.Invoke()) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static void SpinWaitWhile(ref int check, int comparand) |
|
{ |
|
var spinWait = new SpinWait(); |
|
while (Volatile.Read(ref check) == comparand) |
|
{ |
|
spinWait.SpinOnce(); |
|
} |
|
} |
|
|
|
public static void SpinWaitWhile(ref int check, int comparand, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) != comparand) |
|
{ |
|
return; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitWhile(ref int check, int comparand, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
SpinWaitWhile(ref check, comparand); |
|
return true; |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
if (Volatile.Read(ref check) != comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitWhile(ref int check, int comparand, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
SpinWaitWhile(ref check, comparand, cancellationToken); |
|
return true; |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) != comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitWhile(ref int check, int comparand, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
if (Volatile.Read(ref check) != comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitWhile(ref int check, int comparand, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) != comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitWhile(ref int check, int comparand, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
if (Volatile.Read(ref check) != comparand) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitWhile(ref int check, int comparand, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) != comparand) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static void SpinWaitWhileNull<T>(ref T check) |
|
where T : class |
|
{ |
|
var spinWait = new SpinWait(); |
|
while (Volatile.Read(ref check) == null) |
|
{ |
|
spinWait.SpinOnce(); |
|
} |
|
} |
|
|
|
public static void SpinWaitWhileNull<T>(ref T check, CancellationToken cancellationToken) |
|
where T : class |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) != null) |
|
{ |
|
return; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitWhileNull<T>(ref T check, int milliseconds) |
|
where T : class |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
SpinWaitWhileNull(ref check); |
|
return true; |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
if (Volatile.Read(ref check) != null) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitWhileNull<T>(ref T check, int milliseconds, CancellationToken cancellationToken) |
|
where T : class |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
SpinWaitWhileNull(ref check, cancellationToken); |
|
return true; |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) != null) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitWhileNull<T>(ref T check, TimeSpan timeout) |
|
where T : class |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
if (Volatile.Read(ref check) != null) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitWhileNull<T>(ref T check, TimeSpan timeout, CancellationToken cancellationToken) |
|
where T : class |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) != null) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitWhileNull<T>(ref T check, IComparable<TimeSpan> timeout) |
|
where T : class |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
if (Volatile.Read(ref check) != null) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitWhileNull<T>(ref T check, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
where T : class |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
if (Volatile.Read(ref check) != null) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSet(ref int check, int value) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeSet(ref int check, int value, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeSet(ref int check, int value, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeSet(ref check, value); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSet(ref int check, int value, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeSet(ref check, value); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSet(ref int check, int value, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSet(ref int check, int value, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSet(ref int check, int value, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSet(ref int check, int value, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchange(ref int check, int value, out int result) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
result = tmpB + value; |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchange(ref int check, int value, out int result, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
result = tmpB + value; |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchange(ref int check, int value, out int result, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeExchange(ref check, value, out result); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
result = tmpB + value; |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchange(ref int check, int value, out int result, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeExchange(ref check, value, out result); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
result = tmpB + value; |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchange(ref int check, int value, out int result, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
result = tmpB + value; |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchange(ref int check, int value, out int result, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
result = tmpB + value; |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchange(ref int check, int value, out int result, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
result = tmpB + value; |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchange(ref int check, int value, out int result, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var tmpA = Volatile.Read(ref check); |
|
var tmpB = Interlocked.CompareExchange(ref check, tmpA + value, tmpA); |
|
result = tmpB + value; |
|
if (tmpB == tmpA) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSetUnless(ref int check, int value, int comparand, int unless) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, value, comparand); |
|
if (tmpB == comparand) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitSetUnless(ref int check, int value, int comparand, int unless, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, value, comparand); |
|
if (tmpB == comparand) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitSetUnless(ref int check, int value, int comparand, int unless, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitSetUnless(ref check, value, comparand, unless); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, value, comparand); |
|
if (tmpB == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSetUnless(ref int check, int value, int comparand, int unless, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitSetUnless(ref check, value, comparand, unless); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, value, comparand); |
|
if (tmpB == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSetUnless(ref int check, int value, int comparand, int unless, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, value, comparand); |
|
if (tmpB == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSetUnless(ref int check, int value, int comparand, int unless, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, value, comparand); |
|
if (tmpB == comparand) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSetUnless(ref int check, int value, int comparand, int unless, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, value, comparand); |
|
if (tmpB == comparand) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitSetUnless(ref int check, int value, int comparand, int unless, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, value, comparand); |
|
if (tmpB == comparand) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnless(ref int check, int value, int unless) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
var result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnless(ref int check, int value, int unless, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
var result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnless(ref int check, int value, int unless, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeSetUnless(ref check, value, unless); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
var result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnless(ref int check, int value, int unless, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeSetUnless(ref check, value, unless); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
var result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnless(ref int check, int value, int unless, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
var result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnless(ref int check, int value, int unless, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
var result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnless(ref int check, int value, int unless, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
var result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnless(ref int check, int value, int unless, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
var result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnless(ref int check, int value, int unless, out int result) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnless(ref int check, int value, int unless, out int result, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnless(ref int check, int value, int unless, out int result, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeExchangeUnless(ref check, value, unless, out result); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnless(ref int check, int value, int unless, out int result, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeExchangeUnless(ref check, value, unless, out result); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnless(ref int check, int value, int unless, out int result, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnless(ref int check, int value, int unless, out int result, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnless(ref int check, int value, int unless, out int result, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnless(ref int check, int value, int unless, out int result, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
result = lastValue + value; |
|
if (lastValue == unless) |
|
{ |
|
return false; |
|
} |
|
var tmpB = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmpB == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessNegative(ref int check, int value) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessNegative(ref int check, int value, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessNegative(ref int check, int value, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeSetUnlessNegative(ref check, value); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessNegative(ref int check, int value, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeSetUnlessNegative(ref check, value); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessNegative(ref int check, int value, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessNegative(ref int check, int value, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessNegative(ref int check, int value, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessNegative(ref int check, int value, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessNegative(ref int check, int value, out int lastValue) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessNegative(ref int check, int value, out int lastValue, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessNegative(ref int check, int value, out int lastValue, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeExchangeUnlessNegative(ref check, value, out lastValue); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessNegative(ref int check, int value, out int lastValue, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeExchangeUnlessNegative(ref check, value, out lastValue); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessNegative(ref int check, int value, out int lastValue, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessNegative(ref int check, int value, out int lastValue, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessNegative(ref int check, int value, out int lastValue, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessNegative(ref int check, int value, out int lastValue, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < 0) || (lastValue < -value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessExcess(ref int check, int value, int maxValue) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessExcess(ref int check, int value, int maxValue, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessExcess(ref int check, int value, int maxValue, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeSetUnlessExcess(ref check, value, maxValue); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessExcess(ref int check, int value, int maxValue, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeSetUnlessExcess(ref check, value, maxValue); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessExcess(ref int check, int value, int maxValue, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessExcess(ref int check, int value, int maxValue, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessExcess(ref int check, int value, int maxValue, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetUnlessExcess(ref int check, int value, int maxValue, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessExcess(ref int check, int value, int maxValue, out int lastValue) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessExcess(ref int check, int value, int maxValue, out int lastValue, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessExcess(ref int check, int value, int maxValue, out int lastValue, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeExchangeUnlessExcess(ref check, value, maxValue, out lastValue); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessExcess(ref int check, int value, int maxValue, out int lastValue, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeExchangeUnlessExcess(ref check, value, maxValue, out lastValue); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessExcess(ref int check, int value, int maxValue, out int lastValue, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessExcess(ref int check, int value, int maxValue, out int lastValue, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessExcess(ref int check, int value, int maxValue, out int lastValue, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeUnlessExcess(ref int check, int value, int maxValue, out int lastValue, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue > maxValue) || (lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetBounded(ref int check, int value, int minValue, int maxValue) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetBounded(ref int check, int value, int minValue, int maxValue, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetBounded(ref int check, int value, int minValue, int maxValue, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeSetBounded(ref check, value, minValue, maxValue); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetBounded(ref int check, int value, int minValue, int maxValue, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeSetBounded(ref check, value, minValue, maxValue); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetBounded(ref int check, int value, int minValue, int maxValue, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetBounded(ref int check, int value, int minValue, int maxValue, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetBounded(ref int check, int value, int minValue, int maxValue, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeSetBounded(ref int check, int value, int minValue, int maxValue, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
var lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeBounded(ref int check, int value, int minValue, int maxValue, out int lastValue) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeBounded(ref int check, int value, int minValue, int maxValue, out int lastValue, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeBounded(ref int check, int value, int minValue, int maxValue, out int lastValue, int milliseconds) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeExchangeBounded(ref check, value, minValue, maxValue, out lastValue); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeBounded(ref int check, int value, int minValue, int maxValue, out int lastValue, int milliseconds, CancellationToken cancellationToken) |
|
{ |
|
if (milliseconds < -1) |
|
{ |
|
throw new ArgumentOutOfRangeException("milliseconds"); |
|
} |
|
if (milliseconds == -1) |
|
{ |
|
return SpinWaitRelativeExchangeBounded(ref check, value, minValue, maxValue, out lastValue); |
|
} |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeBounded(ref int check, int value, int minValue, int maxValue, out int lastValue, TimeSpan timeout) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeBounded(ref int check, int value, int minValue, int maxValue, out int lastValue, TimeSpan timeout, CancellationToken cancellationToken) |
|
{ |
|
var milliseconds = (long)timeout.TotalMilliseconds; |
|
var spinWait = new SpinWait(); |
|
var start = TicksNow(); |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (Milliseconds(TicksNow() - start) < milliseconds) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeBounded(ref int check, int value, int minValue, int maxValue, out int lastValue, IComparable<TimeSpan> timeout) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
|
|
public static bool SpinWaitRelativeExchangeBounded(ref int check, int value, int minValue, int maxValue, out int lastValue, IComparable<TimeSpan> timeout, CancellationToken cancellationToken) |
|
{ |
|
var spinWait = new SpinWait(); |
|
var start = DateTime.Now; |
|
retry: |
|
cancellationToken.ThrowIfCancellationRequested(); |
|
GC.KeepAlive(cancellationToken.WaitHandle); |
|
lastValue = Volatile.Read(ref check); |
|
if ((lastValue < minValue || lastValue > maxValue) || (lastValue + value < minValue || lastValue > maxValue - value)) |
|
{ |
|
return false; |
|
} |
|
var result = lastValue + value; |
|
var tmp = Interlocked.CompareExchange(ref check, result, lastValue); |
|
if (tmp == lastValue) |
|
{ |
|
return true; |
|
} |
|
if (timeout.CompareTo(DateTime.Now.Subtract(start)) > 0) |
|
{ |
|
spinWait.SpinOnce(); |
|
goto retry; |
|
} |
|
return false; |
|
} |
|
} |
|
} |
|
#endif |