public void close() {
   final Throwable throwable = throwableHolder.get();
   if (throwable != null) {
     throwableHolder.set(null);
     throw Throwables.propagate(throwable);
   }
 }
  /**
   * An {@link Enumerator} that gets its rows from a {@link BlockingQueue}. There are other fields
   * to signal errors and end-of-data.
   */
  private static class BlockingQueueEnumerator<E> implements Enumerator<E> {
    final BlockingQueue<E> queue = new ArrayBlockingQueue<>(1000);
    final AtomicBoolean done = new AtomicBoolean(false);
    final Holder<Throwable> throwableHolder = Holder.of(null);

    E next;

    public E current() {
      if (next == null) {
        throw new NoSuchElementException();
      }
      return next;
    }

    public boolean moveNext() {
      for (; ; ) {
        next = queue.poll();
        if (next != null) {
          return true;
        }
        if (done.get()) {
          close();
          return false;
        }
      }
    }

    public void reset() {}

    public void close() {
      final Throwable throwable = throwableHolder.get();
      if (throwable != null) {
        throwableHolder.set(null);
        throw Throwables.propagate(throwable);
      }
    }
  }