public async ValueTask <bool> Drain(ReplayEnumerator consumer) { for (; ;) { var d = _done; var s = _size; var index = consumer.Index; if (d && s == index) { if (_error != null) { throw _error; } return(false); } if (index != s) { consumer.Current = _values[index]; consumer.Index = index + 1; return(true); } await ResumeHelper.Await(ref consumer.Resume); ResumeHelper.Clear(ref consumer.Resume); } }
private void Remove(ReplayEnumerator inner) { for (; ;) { var a = Volatile.Read(ref _enumerators); var n = a.Length; if (n == 0) { return; } var j = Array.IndexOf(a, inner); if (j < 0) { return; } ReplayEnumerator[] b; if (n == 1) { b = Empty; } else { b = new ReplayEnumerator[n - 1]; Array.Copy(a, 0, b, 0, j); Array.Copy(a, j + 1, b, j, n - j - 1); } if (Interlocked.CompareExchange(ref _enumerators, b, a) == a) { return; } } }
/// <summary> /// Returns an <see cref="IAsyncEnumerator{T}"/> representing an active asynchronous sequence. /// </summary> /// <returns>The active asynchronous sequence to be consumed.</returns> public IAsyncEnumerator <T> GetAsyncEnumerator() { var en = new ReplayEnumerator(this); Add(en); return(en); }
/// <summary> /// Returns an <see cref="IAsyncEnumerator{T}"/> representing an active asynchronous sequence. /// </summary> /// <returns>The active asynchronous sequence to be consumed.</returns> public IAsyncEnumerator <T> GetAsyncEnumerator(CancellationToken cancellationToken) { var en = new ReplayEnumerator(this); Add(en); // FIXME what about the registration??? cancellationToken.Register(v => (v as ReplayEnumerator)?.Cancel(), en); return(en); }
private void Add(ReplayEnumerator inner) { for (; ;) { var a = Volatile.Read(ref _enumerators); if (a == Terminated) { return; } var n = a.Length; var b = new ReplayEnumerator[n + 1]; Array.Copy(a, 0, b, 0, n); b[n] = inner; if (Interlocked.CompareExchange(ref _enumerators, b, a) == a) { return; } } }