public void InnerComplete(InnerSignalObserver <R> sender) { sender.Dispose(); if (Volatile.Read(ref active) == sender) { sender.SetDone(); Drain(); } }
public void InnerError(InnerSignalObserver <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; } for (; ;) { var inner = observers.TryPoll(out var success); if (!success) { break; } 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; } } curr = observers.TryPoll(out var success); var empty = !success; 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 success = false; if (q != null) { try { v = q.TryPoll(out success); } catch (Exception ex) { Interlocked.CompareExchange(ref this.error, ex, null); Volatile.Write(ref disposed, true); continueOuter = true; break; } } if (d && !success) { curr.Dispose(); current = null; curr = null; InnerConsumed(); continueOuter = true; break; } if (!success) { break; } downstream.OnNext(v); } if (continueOuter) { continue; } } } missed = Interlocked.Add(ref wip, -missed); if (missed == 0) { break; } } }