private void SetFinal(Exception error) { Debug.Assert(error is not null); var state = Atomic.Lock(ref _state); switch (state) { case _sInitial: _tsDelay.Reset(); _state = _sFinal; _ctr.Dispose(); _tsDelay.SetException(error); break; case _sWaiting: _state = _sFinal; _ctr.Dispose(); _tsDelay.SetException(error); break; case _sFinal: _state = _sFinal; break; default: _state = state; throw new Exception(_state + "???"); } }
/// <inheritdoc /> public ValueTask <bool> MoveNextAsync() { var state = Atomic.Lock(ref _state); switch (state) { case _sInitial: _state = _sInitial; throw new InvalidOperationException("GetAsyncEnumerator was not called."); case _sEmitting: _tsAccepting.Reset(); _state = _sAccepting; _tsEmitting.SetResult(true); return(_tsAccepting.Task); case _sAccepting: _state = _sAccepting; throw new InvalidOperationException("MoveNextAsync is not reentrant."); case _sFinal: Current = default; _state = _sFinal; return(new(_atmbFinal.Task)); default: _state = state; throw new Exception(state + "???"); } }
private void SetFinal(Exception error) { var state = Atomic.Lock(ref _state); switch (state) { case _sInitial: _state = _sInitial; throw new InvalidOperationException(); case _sEmitting: _state = _sFinal; _ctr.Dispose(); _atmbFinal.SetExceptionOrResult(error, false); _tsEmitting.SetResult(false); break; case _sAccepting: Current = default; _state = _sFinal; _ctr.Dispose(); _atmbFinal.SetExceptionOrResult(error, false); _tsAccepting.SetExceptionOrResult(error, false); break; default: // _sFinal _state = state; break; } }
public ValueTuple <T1, T2>?OnNext2(T2 value) { var missing = Atomic.Lock(ref _missing) & ~(1 << 1); _value2 = value; var result = missing == 0 ? new ValueTuple <T1, T2>(_value1, _value2): default; _missing = missing; return(result); }
private async void MoveNextAsync(Func <ConfiguredValueTaskAwaitable <bool> > moveNext) { bool completed; Exception error; if (_completed) { completed = false; error = null; } else { try { completed = !await moveNext(); error = null; } catch (Exception ex) { completed = true; error = ex; } } var a = Atomic.Lock(ref _active) - 1; if (completed) { if (_completed) // someone was faster, ignore result { completed = false; // prevent cancellation below } else { _completed = true; _error = error; } } _active = a; if (completed) { _cts.TryCancel(); } if (a == 0) { _ts.SetExceptionOrResult(_error, !_completed); } }
public void SetError(Exception error) { var a = Atomic.Lock(ref _active); if (_completed) { _active = a; return; } _completed = true; _error = error; _active = a; _cts.TryCancel(); }
public IAsyncEnumerator <T> GetAsyncEnumerator(CancellationToken token) { if (token.IsCancellationRequested) { return(new LinxAsyncEnumerable.ThrowIterator <T>(new OperationCanceledException(token))); } var state = Atomic.Lock(ref _state); if (state != _sInitial) { _state = state; return(new CoroutineIterator <T>(this).GetAsyncEnumerator(token)); } try { _tsAccepting = new(); _tsEmitting = new(); _tsEmitting.Reset(); _state = _sEmitting; Produce(token); if (token.CanBeCanceled) { _ctr = token.Register(() => SetFinal(new OperationCanceledException(token))); } return(this); } catch (Exception ex) { _state = Atomic.LockBit; Current = default; _tsAccepting = default; _tsEmitting = default; _atmbFinal = default; _atmbDisposed = default; _ctr = default; _state = _sFinal; _atmbFinal.SetException(ex); _atmbDisposed.SetResult(); return(new LinxAsyncEnumerable.ThrowIterator <T>(ex)); } }
public ValueTask Delay(TimeSpan due) { var state = Atomic.Lock(ref _state); switch (state) { case _sInitial: _tsDelay.Reset(); if (due > TimeSpan.Zero) { _state = _sWaiting; try { _timer.Change(due, Timeout.InfiniteTimeSpan); } catch (Exception ex) { if (Atomic.CompareExchange(ref _state, _sInitial, _sWaiting) == _sWaiting) { _tsDelay.SetException(ex); } } } else { _state = _sInitial; _tsDelay.SetResult(); } return(_tsDelay.Task); case _sFinal: _state = _sFinal; return(_tsDelay.Task); case _sWaiting: _state = _sWaiting; throw new InvalidOperationException(Strings.MethodIsNotReentrant); default: _state = state; throw new Exception(state + "???"); } }
private ValueTask <bool> YieldAsync(T item) { var state = Atomic.Lock(ref _state); switch (state) { case _sAccepting: Current = item; _tsEmitting.Reset(); _state = _sEmitting; _tsAccepting.SetResult(true); return(_tsEmitting.Task); case _sFinal: _state = _sFinal; return(new(false)); default: _state = state; throw new InvalidOperationException(state + "???"); } }
/// <summary> /// Prune cache. /// </summary> void Prune(object _discard, System.Timers.ElapsedEventArgs _2) { if (disposed) { return; // dumbness with timers } if (!Atomic.Lock(ref prune_in_progress)) { return; // only one instance. } try { if (Items.Count <= MinCache) { return; // just don't bother } if (Items.Count <= AbsoluteCapacity && CacheEvictStrategy == EvictStrategy.LeastUsed) { return; } var list = Items.Values.ToList(); // would be nice to cache this list list.Sort((CacheItem <TKey, TValue> x, CacheItem <TKey, TValue> y) => { if (CacheEvictStrategy == EvictStrategy.LeastRecent) { if (x.Access < y.Access) { return(-1); } if (x.Access > y.Access) { return(1); } // Both have equal at this point if (x.Desirability < y.Desirability) { return(-1); } if (x.Desirability > y.Desirability) { return(1); } } else // EvictStrategy.LeastUsed { if (x.Desirability < y.Desirability) { return(-1); } if (x.Desirability > y.Desirability) { return(1); } // Both have equal at this point if (x.Access < y.Access) { return(-1); } if (x.Access > y.Access) { return(1); } } return(0); }); while (Items.Count > AbsoluteCapacity) { var bu = list[0]; var key = bu.AccessKey; Items.TryRemove(key, out _); list.Remove(bu); } var deleteItem = new Action <TKey>( (TKey key) => { //Debug.WriteLine($"MKAh.SimpleCache removing {bi:N1} min old item."); if (Items.TryRemove(key, out var item)) { list.Remove(item); } } ); var now = DateTimeOffset.UtcNow; while (list.Count > 0) { var bu = list[0]; double bi = now.Since(bu.Access).TotalMinutes; if (CacheEvictStrategy == EvictStrategy.LeastRecent) { if (bi > MaxAge) { deleteItem(bu.AccessKey); } else { break; } } else // .LeastUsed { if (bi > MinAge) { deleteItem(bu.AccessKey); } else { break; } } } } finally { Atomic.Unlock(ref prune_in_progress); } }