private void NextHandler(Task <bool> t) { if (t.IsFaulted) { ExceptionHelper.AddException(ref _error, ExceptionHelper.Extract(t.Exception)); _done = true; if (TryDispose()) { Signal(); } } else if (t.Result) { IAsyncEnumerator <TResult> src; try { src = _mapper(_source.Current).GetAsyncEnumerator(); } catch (Exception ex) { ExceptionHelper.AddException(ref _error, ex); _done = true; Dispose(_source); Signal(); return; } if (TryDispose()) { Interlocked.Increment(ref _allDisposeWip); var inner = new InnerHandler(src, this); for (; ;) { var curr = Volatile.Read(ref _current); if (curr == DisposedInnerHandler) { inner.Dispose(); break; } if (Interlocked.CompareExchange(ref _current, inner, curr) == curr) { curr?.Dispose(); inner.MoveNext(); MoveNext(); return; } } } } else { _done = true; if (TryDispose()) { Signal(); } } }
private void Handle(Task <bool> task) { if (task.IsCanceled) { AddException(new OperationCanceledException()); _done = true; if (TryDispose()) { Signal(); } } else if (task.IsFaulted) { AddException(task.Exception); _done = true; if (TryDispose()) { Signal(); } } else { if (task.Result) { var v = _source.Current; if (TryDispose()) { var cts = CancellationTokenSource.CreateLinkedTokenSource(_sourceCTS.Token); IAsyncEnumerator <TResult> innerSource; try { innerSource = _mapper(v) .GetAsyncEnumerator(cts.Token); } catch (Exception ex) { _source.DisposeAsync(); AddException(ex); _done = true; Signal(); return; } var handler = new InnerHandler(this, innerSource, _prefetch, cts); Interlocked.Increment(ref _allDisposeWip); if (Add(handler)) { handler.MoveNext(); if (Interlocked.Decrement(ref _outstanding) != 0) { MoveNext(); } } else { // This will decrement _allDisposeWip so // that the DisposeAsync() can be released eventually DisposeOne(); } } } else { _done = true; if (TryDispose()) { Signal(); } } } }
private void NextHandler(Task <bool> t) { if (t.IsFaulted) { ExceptionHelper.AddException(ref _error, ExceptionHelper.Extract(t.Exception)); _sourceDone = true; if (TryDispose()) { ResumeHelper.Resume(ref _resume); } } else if (t.Result) { var cts = CancellationTokenSource.CreateLinkedTokenSource(_ct); IAsyncEnumerator <TResult> src; try { src = _mapper(_source.Current).GetAsyncEnumerator(cts.Token); } catch (Exception ex) { ExceptionHelper.AddException(ref _error, ex); _sourceDone = true; src = null; if (TryDispose()) { ResumeHelper.Resume(ref _resume); return; } } if (src != null) { Interlocked.Increment(ref _disposeWip); var inner = new InnerHandler(src, this, cts); _inners.Enqueue(inner); if (_disposeRequested) { while (_inners.TryDequeue(out var inner2)) { inner2.Dispose(); } } if (TryDispose()) { inner.MoveNext(); if (Interlocked.Decrement(ref _sourceOutstanding) != 0) { MoveNextSource(); } ResumeHelper.Resume(ref _resume); } } } else { _sourceDone = true; if (TryDispose()) { ResumeHelper.Resume(ref _resume); } } }