@Override public void next(Object value) { if (value == null) { fail(new NullPointerException("value is null")); return; } if (done) { Exceptions.onNextDropped(value); return; } if (caughtUp && actual != null) { try { actual.onNext(value); } finally { ch.read(); ReferenceCountUtil.release(value); } } else { Queue<Object> q = queue; if (q == null) { q = QueueSupplier.unbounded().get(); queue = q; } q.offer(value); if (drain()) { caughtUp = true; } } }
/** Resumes the underlying packet reader. */ private void resume() { mChannel.config().setAutoRead(true); mChannel.read(); }
boolean drain() { if (wip++ != 0) { return false; } int missed = 1; for (; ; ) { final Queue<Object> q = queue; final Subscriber<? super Object> a = actual; if (a == null) { return false; } long r = requested; long e = 0L; while (e != r) { if (isCancelled()) { return false; } boolean d = done; Object v = q != null ? q.poll() : null; boolean empty = v == null; if (d && empty) { cancelResource(); if (q != null) { q.clear(); } Throwable ex = error; if (ex != null) { a.onError(ex); } else { a.onComplete(); } return false; } if (empty) { ch.read(); break; } try { a.onNext(v); } finally { ReferenceCountUtil.release(v); ch.read(); } e++; } if (e == r) { if (isCancelled()) { return false; } if (done && (q == null || q.isEmpty())) { cancelResource(); if (q != null) { q.clear(); } Throwable ex = error; if (ex != null) { a.onError(ex); } else { a.onComplete(); } return false; } } if (e != 0L) { if (r != Long.MAX_VALUE) { if ((requested -= e) > 0L) { ch.read(); } } } missed = (wip = wip - missed); if (missed == 0) { if (r == Long.MAX_VALUE) { ch.config().setAutoRead(true); ch.read(); return true; } return false; } } }