public static void SimpleSync() { var control = new int[3]; var thread = new Thread ( () => { var spinWait = new SpinWait(); Volatile.Write(ref control[0], 1); while (Volatile.Read(ref control[1]) == 0) { spinWait.SpinOnce(); } Volatile.Write(ref control[2], 1); } ); thread.Start(); ThreadingHelper.SpinWaitUntil(ref control[0], 1); Volatile.Write(ref control[1], 1); thread.Join(); Assert.AreEqual(1, Volatile.Read(ref control[2])); }
private ManualResetEvent RetriveWaitHandle() { // At the end of this method: _requested will be 2 or ObjectDisposedException is thrown var found = Interlocked.CompareExchange(ref _requested, 1, 0); switch (found) { case -1: throw new ObjectDisposedException(GetType().FullName); case 0: // Found 0, was set to 1, create the wait handle var isSet = Thread.VolatileRead(ref _state) != 0; // State may have been set here var created = new ManualResetEvent(isSet); if (Interlocked.CompareExchange(ref _handle, created, null) != null) { created.Close(); } Thread.VolatileWrite(ref _requested, 2); goto default; case 1: // Found 1, another thread is creating the wait handle ThreadingHelper.SpinWaitUntil(ref _requested, 2); goto default; default: // Found 2, the wait handle is already created // Check if dispose has been called return(TryGetWaitHandleExtracted()); } }
private void CaptureAndWait(LockableSlot slot) { Capture(slot); var thread = Thread.CurrentThread; // The reason while I cannot make an smarter wait function: // If another thread changed _needleLock.Value after the check but before the starting to wait, the wait will not finish. ThreadingHelper.SpinWaitUntil(() => _needleLock.Value == thread); }
internal LockableSlot(LockableContext context) { _context = context; _parent = _context.Slot; _context.Slot = this; // -- LockSlot <Thread> lockSlot = null; ThreadingHelper.SpinWaitUntil(() => _context.Context.ClaimSlot(out lockSlot)); lockSlot.Value = Thread.CurrentThread; _lockSlot = lockSlot; _needleLocks = new List <NeedleLock <Thread> >(); }
public ReadOnlyPromise(IPromise promised, bool allowWait) { _promised = promised; if (allowWait) { if (_promised is IWaitablePromise promise) { _wait = promise.Wait; } else { _wait = () => ThreadingHelper.SpinWaitUntil(() => _promised.IsCompleted); } } else { _wait = () => throw new InvalidOperationException(); } }
private ManualResetEvent GetWaitHandle() { var found = Thread.VolatileRead(ref _requested); switch (found) { case -1: throw new ObjectDisposedException(GetType().FullName); case 0: return(null); case 1: // Found 1, another thread is creating the wait handle ThreadingHelper.SpinWaitUntil(ref _requested, 2); goto default; default: // Found 2, the wait handle is already created // Check if dispose has been called return(TryGetWaitHandleExtracted()); } }
public ReadOnlyPromise(IPromise promised, bool allowWait) { _promised = promised; if (allowWait) { var promise = _promised as IWaitablePromise; if (promise != null) { _wait = () => promise.Wait(); } else { _wait = () => ThreadingHelper.SpinWaitUntil(() => _promised.IsCompleted); } } else { _wait = () => { throw new InvalidOperationException(); }; } }
public bool Commit() { if (_currentTransaction != this) { throw new InvalidOperationException("Cannot commit a non-current transaction."); } ThreadingHelper.MemoryBarrier(); try { if (!CheckValue()) { //the resources has been modified by another thread return(false); } try { ThreadingHelper.SpinWaitUntil(() => Context.ClaimSlot(out LockSlot)); LockSlot.Value = Thread.CurrentThread; if (!Capture()) { //Nothing to commit return(true); } ThreadingHelper.MemoryBarrier(); if (!CheckCapture() || !CheckValue()) { //the resources has been claimed by another thread return(false); } var written = false; foreach (var resource in WriteLog) { if (resource.Key.Commit()) { written = true; } else { //unexpected if (written) { // TODO - the transaction was partially written, this should not be possible. System.Diagnostics.Debug.Fail("unexpected - partially committed transaction"); } return(false); } } return(true); } finally { if (LockSlot != null) { LockSlot.Close(); LockSlot = null; } } } finally { Release(false); } }
public Progressor(IEnumerable <T> preface, Progressor <T> wrapped) { if (wrapped == null) { throw new ArgumentNullException("wrapped"); } if (preface == null) { throw new ArgumentNullException("preface"); } var enumerator = preface.GetEnumerator(); if (enumerator == null) { throw new ArgumentException("preface.GetEnumerator()"); } var control = 0; var guard = 0; Predicate <T> newFilter = item => Thread.VolatileRead(ref control) == 0; var buffer = new SafeQueue <T>(); wrapped.SubscribeAction ( item => { if (newFilter(item)) { buffer.Add(item); } } ); _proxy = new ProxyObservable <T>(); TryTake <T> tryTakeReplacement = (out T value) => { Interlocked.Increment(ref control); try { if (buffer.TryTake(out value) || wrapped.TryTake(out value)) { _proxy.OnNext(value); return(true); } else { _done = wrapped._done; return(false); } } finally { Interlocked.Decrement(ref control); } }; _tryTake = (out T value) => { value = default(T); if (Thread.VolatileRead(ref guard) == 0) { bool result; // We need a lock, there is no way around it. IEnumerator is just awful. Use another overload if possible. lock (enumerator) { result = enumerator.MoveNext(); if (result) { value = enumerator.Current; } } if (result) { _proxy.OnNext(value); return(true); } enumerator.Dispose(); Interlocked.CompareExchange(ref guard, 1, 0); } if (Interlocked.CompareExchange(ref guard, 2, 1) == 1) { _tryTake = tryTakeReplacement; Thread.VolatileWrite(ref guard, 3); } else { ThreadingHelper.SpinWaitUntil(ref guard, 3); } var tryTake = _tryTake; return(tryTake(out value)); }; }
public Progressor(T[] preface, Progressor <T> wrapped) { if (wrapped == null) { throw new ArgumentNullException("wrapped"); } if (preface == null) { throw new ArgumentNullException("preface"); } var control = 0; var guard = 0; var index = -1; Predicate <T> newFilter = item => Thread.VolatileRead(ref control) == 0; var buffer = new SafeQueue <T>(); wrapped.SubscribeAction ( item => { if (newFilter(item)) { buffer.Add(item); } } ); _proxy = new ProxyObservable <T>(); TryTake <T> tryTakeReplacement = (out T value) => { Interlocked.Increment(ref control); try { if (buffer.TryTake(out value) || wrapped.TryTake(out value)) { _proxy.OnNext(value); return(true); } else { _done = wrapped._done; return(false); } } finally { Interlocked.Decrement(ref control); } }; _tryTake = (out T value) => { if (Thread.VolatileRead(ref guard) == 0) { var currentIndex = Interlocked.Increment(ref index); if (currentIndex < preface.Length) { value = preface[currentIndex]; _proxy.OnNext(value); return(true); } Interlocked.CompareExchange(ref guard, 1, 0); } if (Interlocked.CompareExchange(ref guard, 2, 1) == 1) { _tryTake = tryTakeReplacement; Thread.VolatileWrite(ref guard, 3); } else { ThreadingHelper.SpinWaitUntil(ref guard, 3); } var tryTake = _tryTake; return(tryTake(out value)); }; }
public static bool SpinUntil(Func <bool> condition, int millisecondsTimeout) { return(ThreadingHelper.SpinWaitUntil(condition, TimeSpan.FromMilliseconds(millisecondsTimeout))); }
public static void SpinUntil(Func <bool> condition) { ThreadingHelper.SpinWaitUntil(condition); }