public static List<Result> waitForAll(Collection<FutureResult> tasks, long timeoutMs) {
        if (tasks.isEmpty()) return new ArrayList<>();

        // Copy the list in case it is modified while we are waiting
        List<FutureResult> workingTasks = new ArrayList<>(tasks);
        try {
            runTask(tasks.stream().findAny().get().getExecution().context().executor(), () -> {
                for (FutureResult task : workingTasks)
                    task.get(timeoutMs, TimeUnit.MILLISECONDS);
            }).get(timeoutMs, TimeUnit.MILLISECONDS);
        } catch (TimeoutException | InterruptedException | ExecutionException e) {
            // Handle timeouts below
        }

        List<Result> results = new ArrayList<>(tasks.size());
        for (FutureResult atask : workingTasks) {
            Result result;
            if (atask.isDone() && !atask.isCancelled()) {
                result = atask.get(); // Since isDone() = true, this won't block.
            } else { // Not done and no errors thrown
                result = new Result(atask.getQuery(), atask.createTimeoutError());
            }
            results.add(result);
        }
        return results;
    }
Fills this result and returns the future where it is filled.
container-search/src/main/java/com/yahoo/search/searchchain/AsyncExecution.java