private void drain() {
        if (wip++ > 0) {
            return;
        }

        long toRequest = 0L;
        Subscription requestFrom = null;

        do {
            // Get snapshots from values and initialize them
            final long newReq = newRequested;
            newRequested = 0;
            final long newProd = newProduced;
            newProduced = 0;

            final Subscription next = newSubscription;
            final boolean isCancelled = next == NoopSubscription.get();
            if (next != null) {
                newSubscription = null;
            }

            if (isCancelled) {
                final Subscription s = subscription;
                subscription = null;
                if (s != null) {
                    s.cancel();
                }
                toRequest = 0L;
                requestFrom = null;
            } else {
                long currentRequested = requested;

                if (newReq != 0L) {
                    // Accumulate a newly requested number
                    currentRequested = LongMath.saturatedAdd(currentRequested, newReq);
                    toRequest = LongMath.saturatedAdd(toRequest, newReq);
                    requestFrom = subscription;
                }

                if (newProd != 0L && currentRequested != Long.MAX_VALUE) {
                    // Subtract the produced number from the requested number
                    currentRequested = Math.max(currentRequested - newProd, 0);
                }
                if (next != null) {
                    // A new subscription was set. Replace the old subscription with the new one.
                    subscription = next;
                    requestFrom = next;
                    toRequest = currentRequested;
                }
                requested = currentRequested;
            }
        } while (--wip != 0);

        // request outside the serialization loop to avoid certain reentrance issues
        if (requestFrom != null && toRequest != 0L) {
            requestFrom.request(toRequest);
        }
    }
Indicate how many items were produced from the current subscription
before switching to the next subscription.
@param n the number of items produced, positive
core/src/main/java/com/linecorp/armeria/internal/common/stream/SubscriptionArbiter.java