@Override
  public void onNext(T t) {
    synchronized (this) {
      if (emitting) {
        List<T> q = queue;
        if (q == null) {
          q = new ArrayList<T>(4);
          queue = q;
        }
        q.add(t);
        return;
      }
    }
    boolean skipFinal = false;
    try {
      child.onNext(t);

      long r = requested;
      if (r != Long.MAX_VALUE) {
        requested = r - 1;
      }

      emitLoop();
      skipFinal = true;
    } finally {
      if (!skipFinal) {
        synchronized (this) {
          emitting = false;
        }
      }
    }
  }
 @Override
 public void onNext(T t) {
   produced++;
   actual.onNext(t);
 }
  void emitLoop() {
    final Subscriber<? super T> c = child;

    outer:
    for (; ; ) {
      long localRequested;
      Producer localProducer;
      Object localTerminal;
      List<T> q;
      synchronized (this) {
        localRequested = missedRequested;
        localProducer = missedProducer;
        localTerminal = missedTerminal;
        q = queue;
        if (localRequested == 0L && localProducer == null && q == null && localTerminal == null) {
          emitting = false;
          return;
        }
        missedRequested = 0L;
        missedProducer = null;
        queue = null;
        missedTerminal = null;
      }
      boolean empty = q == null || q.isEmpty();
      if (localTerminal != null) {
        if (localTerminal != Boolean.TRUE) {
          c.onError((Throwable) localTerminal);
          return;
        } else if (empty) {
          c.onCompleted();
          return;
        }
      }
      long e = 0;
      if (q != null) {
        for (T v : q) {
          if (c.isUnsubscribed()) {
            return;
          } else if (hasError) {
            continue outer; // if an error has been set, shortcut the loop and act on it
          }
          try {
            c.onNext(v);
          } catch (Throwable ex) {
            Exceptions.throwOrReport(ex, c, v);
            return;
          }
        }
        e += q.size();
      }
      long r = requested;
      // if requested is max, we don't do any accounting
      if (r != Long.MAX_VALUE) {
        // if there were missing requested, add it up
        if (localRequested != 0L) {
          long u = r + localRequested;
          if (u < 0) {
            u = Long.MAX_VALUE;
          }
          r = u;
        }
        // if there were emissions and we don't run on max since the last check, subtract
        if (e != 0L && r != Long.MAX_VALUE) {
          long u = r - e;
          if (u < 0) {
            throw new IllegalStateException("More produced than requested");
          }
          r = u;
        }
        requested = r;
      }
      if (localProducer != null) {
        if (localProducer == NULL_PRODUCER) {
          currentProducer = null;
        } else {
          currentProducer = localProducer;
          if (r != 0L) {
            localProducer.request(r);
          }
        }
      } else {
        Producer p = currentProducer;
        if (p != null && localRequested != 0L) {
          p.request(localRequested);
        }
      }
    }
  }
 @Override
 public void onNext(T t) {
   actual.onNext(t);
 }