public void InnerComplete(InnerObserver <R> sender) { sender.Dispose(); if (Volatile.Read(ref active) == sender) { sender.SetDone(); Drain(); } }
protected void Remove(InnerObserver inner) { if (Volatile.Read(ref disposed)) { return; } lock (this) { if (Volatile.Read(ref disposed)) { return; } disposables.Remove(inner); } inner.Dispose(); }
public void InnerError(InnerObserver <R> sender, Exception error) { sender.Dispose(); if (Volatile.Read(ref active) == sender) { if (delayErrors) { ExceptionHelper.AddException(ref errors, error); sender.SetDone(); Drain(); } else { if (Interlocked.CompareExchange(ref errors, error, null) == null) { sender.SetDone(); Drain(); } } } }
void DrainLoop() { int missed = 1; var observers = this.observers; for (; ;) { if (Volatile.Read(ref disposed)) { if (current != null) { current.Dispose(); current = null; } while (observers.TryPoll(out var inner)) { inner.Dispose(); } Cleanup(); } else { var curr = current; if (curr == null) { var d = Volatile.Read(ref done); if (d) { var ex = Volatile.Read(ref error); if (ex != null) { downstream.OnError(ex); Volatile.Write(ref disposed, true); base.Dispose(); continue; } } var empty = !observers.TryPoll(out curr); if (d && empty) { downstream.OnCompleted(); Volatile.Write(ref disposed, true); base.Dispose(); } current = curr; } if (curr != null) { var continueOuter = false; for (; ;) { if (Volatile.Read(ref disposed)) { continueOuter = true; break; } var d = curr.IsDone(); var q = curr.GetQueue(); var v = default(R); var empty = q == null || !q.TryPoll(out v); if (d && empty) { curr.Dispose(); current = null; curr = null; InnerConsumed(); continueOuter = true; break; } if (empty) { break; } downstream.OnNext(v); } if (continueOuter) { continue; } } } missed = Interlocked.Add(ref wip, -missed); if (missed == 0) { break; } } }