@Override public void call(final Subscriber<? super T> s) { if (state.casFirst(0, 1)) { final NotificationLite<T> nl = NotificationLite.instance(); // drain queued notifications before subscription // we do this here before PassThruObserver so the consuming thread can do this before // putting itself in the line of the producer BufferedObserver<? super T> buffered = (BufferedObserver<? super T>) state.observerRef; Object o; while ((o = buffered.buffer.poll()) != null) { nl.accept(s, o); } // register real observer for pass-thru ... and drain any further events received on first // notification state.setObserverRef(new PassThruObserver<T>(s, buffered.buffer, state)); s.add( Subscriptions.create( new Action0() { @Override public void call() { state.setObserverRef(Subscribers.empty()); } })); } else { s.onError(new IllegalStateException("Only one subscriber allowed!")); } }
private void drainIfNeededAndSwitchToActual() { Object o; while ((o = buffer.poll()) != null) { nl.accept(this, o); } // now we can safely change over to the actual and get rid of the pass-thru // but only if not unsubscribed observerRef.compareAndSet(this, actual); }
private void drainIfNeededAndSwitchToActual() { final NotificationLite<T> nl = NotificationLite.instance(); Object o; while ((o = buffer.poll()) != null) { nl.accept(this, o); } // now we can safely change over to the actual and get rid of the pass-thru // but only if not unsubscribed state.casObserverRef(this, actual); }
protected void drain() { synchronized (this) { if (emitting) { missedEmitting++; return; } emitting = true; missedEmitting = 0; } final List<SourceSubscriber<T>.MergeItemSubscriber> subs = subscribers; final Subscriber<T> child = s; Object[] active = new Object[subs.size()]; do { long r; outer: while ((r = requested) > 0) { int idx = lastIndex; synchronized (subs) { if (subs.size() == active.length) { active = subs.toArray(active); } else { active = subs.toArray(); } } int resumeIndex = 0; int j = 0; for (Object o : active) { @SuppressWarnings("unchecked") MergeItemSubscriber e = (MergeItemSubscriber) o; if (e.index == idx) { resumeIndex = j; break; } j++; } int sumConsumed = 0; for (int i = 0; i < active.length; i++) { j = (i + resumeIndex) % active.length; @SuppressWarnings("unchecked") final MergeItemSubscriber e = (MergeItemSubscriber) active[j]; final RxRingBuffer b = e.buffer; lastIndex = e.index; if (!e.once && b.peek() == null) { subs.remove(e); synchronized (guard) { this.active--; } csub.remove(e); e.release(); subscribeNext(); WIP.decrementAndGet(this); continue outer; } int consumed = 0; Object v; while (r > 0 && (v = b.poll()) != null) { nl.accept(child, v); if (child.isUnsubscribed()) { return; } r--; consumed++; } if (consumed > 0) { sumConsumed += consumed; REQUESTED.addAndGet(this, -consumed); e.requestMore(consumed); } if (r == 0) { break outer; } } if (sumConsumed == 0) { break; } } if (active.length == 0) { if (wip == 0) { child.onCompleted(); return; } } synchronized (this) { if (missedEmitting == 0) { emitting = false; break; } missedEmitting = 0; } } while (true); }