private void Start(long dueTime) { if (dueTime < -1) { throw new ArgumentOutOfRangeException(nameof(dueTime)); } if (Interlocked.CompareExchange(ref _status, _started, _created) == _created) { _startTime = ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow()); _targetTime = dueTime == -1 ? -1 : _startTime + dueTime; _wrapped = Timer.GetTimer(Finish, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(-1)); } }
private static void Initialize() { switch (Interlocked.CompareExchange(ref _status, _statusPending, _statusNotReady)) { case _statusNotReady: GC.KeepAlive(new GCProbe()); Volatile.Write(ref _status, _statusReady); break; case _statusPending: ThreadingHelper.SpinWaitUntil(ref _status, _statusReady); break; } }
public static void TimeoutFinishAndChange() { var value = new[] { 0 }; var timeout = RootedTimeout.Launch(() => value[0] = 1, 100); Assert.IsFalse(timeout.IsCanceled); ThreadingHelper.SpinWaitUntil(() => timeout.IsCompleted); Assert.IsFalse(timeout.IsCanceled); Assert.IsTrue(timeout.IsCompleted); Assert.AreEqual(1, value[0]); Assert.IsFalse(timeout.Change(1000)); Assert.IsFalse(timeout.IsCanceled); Assert.IsTrue(timeout.IsCompleted); }
private void Finish() { ThreadingHelper.SpinWaitWhile(ref _status, _changing); if (Interlocked.CompareExchange(ref _status, _executing, _created) == _created) { var callback = Volatile.Read(ref Callback); if (callback != null) { callback.Invoke(); Close(); Volatile.Write(ref _status, _executed); } } }
public long CheckRemaining() { if (_targetTime == -1) { return(-1); } var remaining = _targetTime - ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow()); if (remaining <= 0) { Finish(null); return(0); } return(remaining); }
private void WaitCanWrite() { if (Thread.CurrentThread != ThreadingHelper.VolatileRead(ref _ownerThread)) { var check = Interlocked.CompareExchange(ref _master, -1, 0); while (true) { switch (check) { case -2: // Write mode already requested case -1: // There is another writer // Go to wait _freeToWrite.Wait(); check = Interlocked.CompareExchange(ref _master, -1, 0); break; case 0: // Free to proceed // GO! _freeToRead.Reset(); if (Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null) == null) { // Success Interlocked.Increment(ref _writeCount); return; } else { // It was reserved by another thread break; } case 1: // There are readers currently // Requesting write mode check = Interlocked.CompareExchange(ref _master, -2, 1); if (check == 1) { _freeToRead.Reset(); check = -2; } break; } } } }
private static void Initialize() { var check = Interlocked.CompareExchange(ref _status, INT_StatusPending, INT_StatusNotReady); switch (check) { case INT_StatusNotReady: GC.KeepAlive(new GCProbe()); Thread.VolatileWrite(ref _status, INT_StatusReady); break; case INT_StatusPending: ThreadingHelper.SpinWaitUntil(ref _status, INT_StatusReady); break; } }
public static void TimeoutChange() { again: var now = DateTime.Now; var value = new[] { now }; var timeout = RootedTimeout.Launch(() => value[0] = DateTime.Now, 100); if (!timeout.Change(1000)) { goto again; } Assert.IsFalse(timeout.IsCanceled); Assert.IsFalse(timeout.IsCompleted); ThreadingHelper.SpinWaitUntil(() => timeout.IsCompleted); Assert.Greater((value[0] - now).TotalMilliseconds, 100); }
public TReturn DisposedConditional <TReturn>(Func <TReturn> whenDisposed, Func <TReturn> whenNotDisposed) { if (_status == -1) { if (ReferenceEquals(whenDisposed, null)) { return(default(TReturn)); } else { return(whenDisposed.Invoke()); } } else { if (ReferenceEquals(whenNotDisposed, null)) { return(default(TReturn)); } else { if (ThreadingHelper.SpinWaitRelativeSet(ref _status, 1, -1)) { try { return(whenNotDisposed.Invoke()); } finally { System.Threading.Interlocked.Decrement(ref _status); } } else { if (ReferenceEquals(whenDisposed, null)) { return(default(TReturn)); } else { return(whenDisposed.Invoke()); } } } } }
private bool CanRead() { if (Thread.CurrentThread == ThreadingHelper.VolatileRead(ref _ownerThread)) { Interlocked.Increment(ref _readCount); _currentReadingCount.Value++; return(true); } if (Interlocked.CompareExchange(ref _master, 1, 0) >= 0) { _freeToWrite.Reset(); Interlocked.Increment(ref _readCount); _currentReadingCount.Value++; return(true); } return(false); }
/// <summary> /// Adds the specified item at the front. /// </summary> /// <param name="item">The item.</param> public void Enqueue(T item) { bool result = false; while (true) { if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { Interlocked.Increment(ref _workingThreads); if (entries.Enqueue(item)) { result = true; } } finally { Interlocked.Decrement(ref _workingThreads); if (result) { Interlocked.Increment(ref _count); done = true; } else { var oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.GrowRequested, (int)BucketStatus.Free); if (oldStatus == (int)BucketStatus.Free) { _revision++; } } } if (done) { return; } } else { CooperativeGrow(); } } }
public bool Change(long dueTime) { if (Interlocked.CompareExchange(ref _status, _changing, _created) == _created) { _startTime = ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow()); _targetTime = _startTime + dueTime; var wrapped = Interlocked.CompareExchange(ref _wrapped, null, null); if (wrapped == null) { return(false); } wrapped.Change(TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(-1)); Volatile.Write(ref _status, _created); return(true); } return(false); }
protected void Start(long dueTime) { if (dueTime < -1) { throw new ArgumentOutOfRangeException("dueTime"); } _startTime = ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow()); if (dueTime == -1) { _targetTime = -1; } else { _targetTime = _startTime + dueTime; } _wrapped = new Timer(Finish, null, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(-1)); }
public static void TimeoutChange() { RootedTimeout timeout; var value = new DateTime[1]; DateTime now; do { now = DateTime.Now; value[0] = now; timeout = RootedTimeout.Launch(() => value[0] = DateTime.Now, 100); }while (!timeout.Change(1000)); Assert.IsFalse(timeout.IsCanceled); Assert.IsFalse(timeout.IsCompleted); ThreadingHelper.SpinWaitUntil(() => timeout.IsCompleted); Assert.Greater((value[0] - now).TotalMilliseconds, 100); }
private void Initialize(long dueTime) { if (Thread.VolatileRead(ref _executed) == 1) { ThreadingHelper.SpinWaitWhile(ref _completed, 1); Thread.VolatileWrite(ref _executed, 0); } _start = ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow()); _targetTime = _start + dueTime; if (_wrapped == null) { _wrapped = new Timer(Callback, null, dueTime, System.Threading.Timeout.Infinite); } else { _wrapped.Change(dueTime, System.Threading.Timeout.Infinite); } }
/// <summary> /// Tries to retrieve the key and associated value at the specified index. /// </summary> /// <param name="index">The index.</param> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <returns> /// <c>true</c> if the value was retrieved; otherwise, <c>false</c>. /// </returns> public bool TryGet(int index, out TKey key, out TValue value) { value = default(TValue); key = default(TKey); bool result = false; int revision; while (true) { revision = _revision; if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { TValue tmpValue; TKey tmpKey; if (TryGetExtracted(index, entries, out tmpKey, out tmpValue)) { key = tmpKey; value = tmpValue; result = true; } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { done = true; } } if (done) { return(result); } } else { CooperativeGrow(); } } }
private void Finish() { ThreadingHelper.SpinWaitWhile(ref _status, _changing); if (Interlocked.CompareExchange(ref _status, _executing, _started) != _started) { return; } var callback = Volatile.Read(ref _callback); if (callback == null) { return; } callback.Invoke(); Volatile.Write(ref _status, _executed); Close(); }
/// <summary> /// Removes the specified key. /// </summary> /// <param name="key">The key.</param> /// <returns> /// <c>true</c> if the specified key was removed; otherwise, <c>false</c>. /// </returns> public bool Remove(TKey key) { bool result = false; int revision; while (true) { revision = _revision; if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { if (RemoveExtracted(key, entries)) { result = true; } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { if (result) { Interlocked.Decrement(ref _count); } done = true; } } if (done) { return(result); } } else { CooperativeGrow(); } } }
private bool CanWrite() { if (Thread.CurrentThread == ThreadingHelper.VolatileRead(ref _ownerThread)) { Interlocked.Increment(ref _writeCount); return(true); } if (Interlocked.CompareExchange(ref _master, -1, 0) == 0) { _freeToRead.Reset(); // -- if (Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null) == null) { // Success Interlocked.Increment(ref _writeCount); return(true); } } return(false); }
public Timeout(Action callback, long dueTime, CancellationToken token) { if (callback == null) { throw new NullReferenceException("callback"); } _start = ThreadingHelper.TicksNow(); if (token.IsCancellationRequested) { _callback = null; _wrapped = null; } else { _callback = callback; Initialize(dueTime); token.Register(Cancel); } _hashcode = unchecked ((int)DateTime.Now.Ticks); }
/// <summary> /// Attempts to retrieve and remove the next item from the back. /// </summary> /// <param name="item">The item.</param> /// <returns> /// <c>true</c> if the item was taken; otherwise, <c>false</c>. /// </returns> public bool TryDequeue(out T item) { item = default(T); bool result = false; while (true) { if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { Interlocked.Increment(ref _workingThreads); T tmpItem; if (entries.TryDequeue(out tmpItem)) { item = tmpItem; result = true; } } finally { Interlocked.Decrement(ref _workingThreads); if (result) { Interlocked.Decrement(ref _count); } done = true; } if (done) { return(result); } } else { CooperativeGrow(); } } }
/// <summary> /// Tries to retrieve the item at the specified index. /// </summary> /// <param name="index">The index.</param> /// <param name="item">The item.</param> /// <returns> /// <c>true</c> if the item was retrieved; otherwise, <c>false</c>. /// </returns> public bool TryGet(int index, out T item) { item = default(T); bool result = false; int revision; while (true) { revision = _revision; if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { T tmpItem; if (TryGetExtracted(index, entries, out tmpItem)) { item = tmpItem; result = true; } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { done = true; } } if (done) { return(result); } } else { CooperativeGrow(); } } }
private bool CanUpgrade() { if (Thread.CurrentThread == ThreadingHelper.VolatileRead(ref _ownerThread)) { Interlocked.Increment(ref _writeCount); return(true); } var check = Interlocked.CompareExchange(ref _master, -2, 1); if (check == 1) { _freeToRead.Reset(); // -- if (Thread.VolatileRead(ref _readCount) <= _currentReadingCount.Value && Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null) == null) { Thread.VolatileWrite(ref _master, -1); Interlocked.Increment(ref _writeCount); return(true); } } return(false); }
private void DoneRead() { if (Thread.CurrentThread == ThreadingHelper.VolatileRead(ref _ownerThread)) { Interlocked.Decrement(ref _readCount); } else { if (Thread.VolatileRead(ref _master) < 0) { if (Interlocked.Decrement(ref _readCount) <= Thread.VolatileRead(ref _edge)) { Thread.VolatileWrite(ref _master, 0); _freeToWrite.Set(); } } else { Interlocked.Decrement(ref _readCount); } } }
/// <summary> /// Determines whether the specified key is contained. /// </summary> /// <param name="key">The key.</param> /// <returns> /// <c>true</c> if the specified key is contained; otherwise, <c>false</c>. /// </returns> public bool ContainsKey(TKey key) { bool result = false; int revision; while (true) { revision = _revision; if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { if (ContainsKeyExtracted(key, entries)) { result = true; } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { done = true; } } if (done) { return(result); } } else { CooperativeGrow(); } } }
private bool WaitUpgrade() { var owner = ThreadingHelper.VolatileRead(ref _ownerThread); if (owner == null || owner == Thread.CurrentThread) { var check = 1; while (true) { switch (check) { case -2: // Write mode already requested // We are going to steal it // Reserve the lock - so no other writer can take it owner = Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null); if (owner == null || owner == Thread.CurrentThread) { // Set the edge Thread.VolatileWrite(ref _edge, _currentReadingCount.Value); } else { // It was reserved by another thread - abort mission return(false); } if (Thread.VolatileRead(ref _readCount) > Thread.VolatileRead(ref _edge)) { // We still need every other reader to finish _freeToWrite.Wait(); check = Interlocked.CompareExchange(ref _master, -1, 0); } else { // None to wait Thread.VolatileWrite(ref _master, -1); check = -1; } break; case -1: // There is a writer // Abort mission _freeToRead.Reset(); Interlocked.Increment(ref _writeCount); return(true); case 0: // Free to proceed return(true); case 1: // There are readers currently - of course, current thread is a reader // Requesting write mode check = Interlocked.CompareExchange(ref _master, -2, 1); if (check == 1) { _freeToRead.Reset(); check = -2; } break; } } } return(false); }
/// <summary> /// Attempts to add the specified key and associated value. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <returns>The value found in the destination after the attempt, regardless of collisions.</returns> public TValue TryAdd(TKey key, TValue value) { bool result = false; int revision; KeyValuePair <TKey, TValue> previous = default(KeyValuePair <TKey, TValue>); TValue found = value; while (true) { revision = _revision; if (IsOperationSafe()) { bool isCollision = false; var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { if (TryAddExtracted(key, value, entries, out previous) != -1) { result = true; } else { isCollision = !_keyComparer.Equals(previous.Key, key); } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { if (result) { Interlocked.Increment(ref _count); done = true; } else { if (isCollision) { var oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.GrowRequested, (int)BucketStatus.Free); if (oldStatus == (int)BucketStatus.Free) { _revision++; } } else { done = true; found = previous.Value; } } } } if (done) { return(found); } } else { CooperativeGrow(); } } }
private bool TakeDisposalExecution() { return(_status != -1 && ThreadingHelper.SpinWaitSetUnless(ref _status, -1, 0, -1)); }
protected void Start(long dueTime) { _startTime = ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow()); _targetTime = _startTime + dueTime; _wrapped = new Timer(Finish, null, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(-1)); }