void scheduleTimeout(long idx) {
      Disposable d = timer;
      if (d != null) {
        d.dispose();
      }

      if (TIMER.compareAndSet(this, d, NEW_TIMER)) {
        d =
            worker.schedule(
                () -> {
                  if (idx == index) {
                    done = true;
                    s.dispose();
                    dispose();

                    actual.onError(new TimeoutException());
                  }
                },
                timeout,
                unit);

        if (!TIMER.compareAndSet(this, NEW_TIMER, d)) {
          d.dispose();
        }
      }
    }
    @Override
    public void accept(final NbpSubscriber<? super String> NbpObserver) {
      NbpObserver.onSubscribe(EmptyDisposable.INSTANCE);
      t =
          new Thread(
              new Runnable() {

                @Override
                public void run() {
                  for (String s : valuesToReturn) {
                    if (s == null) {
                      System.out.println("throwing exception");
                      try {
                        Thread.sleep(100);
                      } catch (Throwable e) {

                      }
                      NbpObserver.onError(new NullPointerException());
                      return;
                    } else {
                      NbpObserver.onNext(s);
                    }
                  }
                  System.out.println("subscription complete");
                  NbpObserver.onComplete();
                }
              });
      t.start();
    }
    @Override
    public void onComplete() {
      if (done) {
        return;
      }
      done = true;
      dispose();

      actual.onComplete();
    }
    @Override
    public void onSubscribe(Disposable s) {
      if (SubscriptionHelper.validateDisposable(this.s, s)) {
        return;
      }

      this.s = s;
      actual.onSubscribe(s);
      scheduleTimeout(0L);
    }
    @Override
    public void onError(Throwable t) {
      if (done) {
        RxJavaPlugins.onError(t);
        return;
      }
      done = true;
      dispose();

      actual.onError(t);
    }
    @Override
    public void onNext(T t) {
      if (done) {
        return;
      }
      long idx = index + 1;
      index = idx;

      actual.onNext(t);

      scheduleTimeout(idx);
    }