public void OnNext(T t) { var s = capacityHint; var item = tail; var i = item.count; if (i == s) { var b = new PublisherCacheItem(s); b.array[0] = t; b.count = 1; item.svNext(b); tail = b; } else { item.array[i] = t; item.svCount(i + 1); } foreach (var inner in Volatile.Read(ref subscribers)) { inner.Drain(); } }
public PublisherCacheInner(ISubscriber <T> actual, PublisherCache <T> parent, int bufferSize, PublisherCacheItem h) { this.actual = actual; this.parent = parent; this.bufferSize = bufferSize; this.current = h; }
public PublisherCache(IPublisher <T> source, int capacityHint) { this.source = source; this.capacityHint = capacityHint; PublisherCacheItem h = new PublisherCacheItem(capacityHint); head = h; tail = h; }
internal void Drain() { if (!bp.Enter()) { return; } PublisherCache <T> p = parent; ISubscriber <T> a = actual; PublisherCacheItem item = current; int c = offset; int missed = 1; long r = bp.Requested(); long e = 0L; for (;;) { if (IsCancelled()) { return; } if (CheckTerminated(p.IsDone(), item.lvCount() == c && item.lvNext() == null, a, p)) { return; } while (r != e) { if (IsCancelled()) { return; } bool d = p.IsDone(); var next = item.lvNext(); var f = item.lvCount(); bool empty = f == c && next == null; if (CheckTerminated(d, empty, a, p)) { return; } if (empty) { break; } if (f == c) { item = next; c = 0; } T v = item.array[c]; c++; } if (CheckTerminated(p.IsDone(), item.lvCount() == c && item.lvNext() == null, a, p)) { return; } r = bp.Requested(); if (e == r) { current = item; offset = c; r = bp.Produced(e); if (r != 0L) { e = 0L; continue; } } missed = bp.Leave(missed); if (missed == 0) { break; } } }
internal void svNext(PublisherCacheItem next) { Volatile.Write(ref this.next, next); }