docs: @Beta
    public static <T> ImmutableList<ListenableFuture<T>> inCompletionOrder(
        Iterable<? extends ListenableFuture<? extends T>> futures) {
      // A CLQ may be overkill here.  We could save some pointers/memory by synchronizing on an
      // ArrayDeque
      final ConcurrentLinkedQueue<AsyncSettableFuture<T>> delegates =
          Queues.newConcurrentLinkedQueue();
      ImmutableList.Builder<ListenableFuture<T>> listBuilder = ImmutableList.builder();
      // Using SerializingExecutor here will ensure that each CompletionOrderListener executes
      // atomically and therefore that each returned future is guaranteed to be in completion order.
      // N.B. there are some cases where the use of this executor could have possibly surprising
      // effects when input futures finish at approximately the same time _and_ the output futures
      // have directExecutor listeners. In this situation, the listeners may end up running on a
      // different thread than if they were attached to the corresponding input future.  We believe
      // this to be a negligible cost since:
      // 1. Using the directExecutor implies that your callback is safe to run on any thread.
      // 2. This would likely only be noticeable if you were doing something expensive or blocking on
      //    a directExecutor listener on one of the output futures which is an antipattern anyway.
      SerializingExecutor executor = new SerializingExecutor(directExecutor());
      for (final ListenableFuture<? extends T> future : futures) {
        AsyncSettableFuture<T> delegate = AsyncSettableFuture.create();
        // Must make sure to add the delegate to the queue first in case the future is already done
        delegates.add(delegate);
        future.addListener(new Runnable() {
          @Override public void run() {
            delegates.remove().setFuture(future);
          }
        }, executor);
        listBuilder.add(delegate);
      }
      return listBuilder.build();
    }