/**
  * Internal conversion method to convert CompletableFutures to FastFuture.
  *
  * @param cf
  * @return
  */
 public static <T> FastFuture<T> fromCompletableFuture(CompletableFuture<T> cf) {
   FastFuture<T> f = new FastFuture<>();
   cf.thenAccept(i -> f.set(i));
   cf.exceptionally(
       t -> {
         f.completedExceptionally(t);
         return f.join();
       });
   return f;
 }
  public static <R> FastFuture<List<R>> anyOf(FastFuture... futures) {

    FastFuture anyOf = new FastFuture();

    for (FastFuture next : futures) {
      next.onComplete(
          v -> {
            anyOf.result.lazySet(true);
            anyOf.done();
          });
    }
    return anyOf;
  }
  /*
   *	@param t Result type
   * @see java.util.function.Consumer#accept(java.lang.Object)
   */
  @Override
  public void accept(FastFuture<T> t) {

    active.add(t);

    if (active.size() > maxActive.getMaxActive()) {

      while (active.size() > maxActive.getReduceTo()) {

        List<FastFuture> toRemove =
            active
                .stream()
                .filter(cf -> cf.isDone())
                .peek(this::handleExceptions)
                .collect(Collectors.toList());

        active.removeAll(toRemove);
        if (active.size() > maxActive.getReduceTo()) {
          CompletableFuture promise = new CompletableFuture();
          FastFuture.xOf(
              active.size() - maxActive.getReduceTo(),
              () -> promise.complete(true),
              active.toArray(new FastFuture[0]));

          promise.join();
        }
      }
    }
  }
  public static <R> FastFuture<List<R>> xOf(int x, Runnable onComplete, FastFuture... futures) {
    // needs to use onComplete
    FastFuture xOf = new FastFuture(FinalPipeline.empty(), x);
    for (FastFuture next : futures) {
      AtomicInteger count = new AtomicInteger(0);
      next.onComplete(
          v -> {
            if (!count.compareAndSet(0, 1)) return;
            if (xOf.count.incrementAndGet() >= xOf.max.get()) {

              onComplete.run();
            }
          });
    }
    return xOf;
  }
 private void handleExceptions(FastFuture cf) {
   if (cf.isCompletedExceptionally()) safeJoin.apply(cf);
 }
 public static <T> FastFuture<T> completedFuture(T value) {
   FastFuture<T> f = new FastFuture();
   f.result.lazySet(value);
   f.done = true;
   return f;
 }