[concurrency-interest] CompletionStage defensive copy

Pavel Rappo pavel.rappo at gmail.com
Wed Aug 31 08:55:13 EDT 2016


I would appreciate if you could provide some feedback on the the following
convenience (yet paranoid?) method I would like to use for defensive copying of


 * Creates a defensive copy of the given {@code CompletionStage}.
 * <p> Might be useful both for producers and consumers of {@code
 * CompletionStage}s.
 * <p> Producers are protected from possible uncontrolled modifications
 * (cancellation, completion, obtrusion, etc.) as well as from executing
 * unknown potentially lengthy or faulty dependants in the given {@code
 * CompletionStage}'s default execution facility or synchronously.
 * <p> Consumers are protected from some of the aspects of misbehaving
 * implementations (e.g. accepting results, applying functions, running
 * tasks, etc. more than once) as well as from escaping of a reference
 * to their private executor by providing a reliable proxy they use instead.
 * @param src
 *         the {@code CompletionStage} to make a copy from
 * @param executor
 *         the executor used to propagate the completion
 * @param <T>
 *         the type of the {@code CompletionStage}'s result
 * @return a copy of the given stage
public static <T> CompletableFuture<T> copy(CompletionStage<T> src,
                                            Executor executor) {
    CompletableFuture<T> copy = new CompletableFuture<>();
    BiConsumer<T, Throwable> relay =
            (result, error) -> {
                if (error != null) {
                } else {
    if (src.getClass() == CompletableFuture.class) {
        // No subclasses! Strictly genuine CompletableFuture.
        src.whenCompleteAsync(relay, executor);
        return copy;
    } else {
        // Don't give our executor away to an unknown CS!
        return copy.thenApplyAsync(Function.identity(), executor);

More information about the Concurrency-interest mailing list