private void Remove(MulticastEnumerator 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; } MulticastEnumerator[] b; if (n == 1) { b = Empty; } else { b = new MulticastEnumerator[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 MulticastEnumerator(this); if (Add(en)) { return(en); } if (_error != null) { return(new Error <T> .ErrorEnumerator(_error)); } return(new Empty <T>()); }
/// <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 MulticastEnumerator(this); if (Add(en)) { // FIXME what about the registration??? cancellationToken.Register(v => (v as MulticastEnumerator)?.Cancel(), en); return(en); } if (_error != null) { return(new Error <T> .ErrorEnumerator(_error)); } return(new Empty <T>()); }
private bool Add(MulticastEnumerator inner) { for (; ;) { var a = Volatile.Read(ref _enumerators); if (a == Terminated) { return(false); } var n = a.Length; var b = new MulticastEnumerator[n + 1]; Array.Copy(a, 0, b, 0, n); b[n] = inner; if (Interlocked.CompareExchange(ref _enumerators, b, a) == a) { return(true); } } }