internal void Subscribe(ISubscriber <T> s) { PublisherReplayInner inner = new PublisherReplayInner(s, this); s.OnSubscribe(inner); Add(inner); if (inner.IsCancelled()) { Remove(inner); } else { Drain(inner); } }
bool CheckTerminated(bool d, bool empty, PublisherReplayInner inner, ISubscriber <T> a) { if (inner.IsCancelled()) { inner.current = null; return(true); } if (d && empty) { Exception e = error; if (e != null) { a.OnError(e); } else { a.OnComplete(); } return(true); } return(false); }
void Remove(PublisherReplayInner inner) { ProcessorHelper.Remove(ref subscribers, inner, Terminated, Empty); }
void Add(PublisherReplayInner inner) { ProcessorHelper.Add(ref subscribers, inner, Terminated); }
void Drain(PublisherReplayInner inner) { if (!inner.Enter()) { return; } int missed = 1; ISubscriber <T> a = inner.actual; for (;;) { bool d = Volatile.Read(ref done); Node current = inner.current; int offset = inner.offset; T[] array = current.array; bool empty = current.LvNext() == null && current.LvCount() == offset; if (CheckTerminated(d, empty, inner, a)) { return; } long r = inner.Requested(); long e = 0L; while (e != r) { d = Volatile.Read(ref done); current = inner.current; offset = inner.offset; Node next = current.LvNext(); int c = current.LvCount(); empty = next == null && c == offset; if (CheckTerminated(d, empty, inner, a)) { return; } if (empty) { break; } if (c == offset && next != null) { current = next; array = next.array; offset = 0; } T t = array[offset]; a.OnNext(t); offset++; e++; } if (e == r) { d = Volatile.Read(ref done); current = inner.current; offset = inner.offset; empty = current.LvNext() == null && current.LvCount() == offset; if (CheckTerminated(d, empty, inner, a)) { return; } } if (e != 0) { inner.Produced(e); } inner.current = current; inner.offset = offset; missed = inner.Leave(missed); if (missed == 0) { break; } } }