1 /* 2 * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.incubator.http.internal.common; 27 28 import java.util.concurrent.CompletableFuture; 29 import java.util.concurrent.CompletionException; 30 import java.util.concurrent.CompletionStage; 31 import java.util.concurrent.Executor; 32 import java.util.function.BiConsumer; 33 import java.util.function.Function; 34 35 import static java.util.Objects.requireNonNull; 36 import java.util.concurrent.atomic.AtomicLong; 37 38 /* 39 * A CompletableFuture which does not allow any obtrusion logic. 40 * All methods of CompletionStage return instances of this class. 41 */ 42 public final class MinimalFuture<T> extends CompletableFuture<T> { 43 44 @FunctionalInterface 45 public interface ExceptionalSupplier<U> { 46 U get() throws Throwable; 47 } 48 49 final static AtomicLong TOKENS = new AtomicLong(); 50 final long id; 51 52 public static <U> MinimalFuture<U> completedFuture(U value) { 53 MinimalFuture<U> f = new MinimalFuture<>(); 54 f.complete(value); 55 return f; 56 } 57 58 public static <U> CompletableFuture<U> failedFuture(Throwable ex) { 59 requireNonNull(ex); 60 MinimalFuture<U> f = new MinimalFuture<>(); 61 f.completeExceptionally(ex); 62 return f; 63 } 64 65 public static <U> CompletableFuture<U> supply(ExceptionalSupplier<U> supplier) { 66 CompletableFuture<U> cf = new MinimalFuture<>(); 67 try { 68 U value = supplier.get(); 69 cf.complete(value); 70 } catch (Throwable t) { 71 cf.completeExceptionally(t); 72 } 73 return cf; 74 } 75 76 public static <U> CompletableFuture<U> supply(ExceptionalSupplier<U> supplier, Executor executor) { 77 CompletableFuture<U> cf = new MinimalFuture<>(); 78 cf.completeAsync( () -> { 79 try { 80 return supplier.get(); 81 } catch (Throwable ex) { 82 throw new CompletionException(ex); 83 } 84 }, executor); 85 return cf; 86 } 87 88 public MinimalFuture() { 89 super(); 90 this.id = TOKENS.incrementAndGet(); 91 } 92 93 /** 94 * Creates a defensive copy of the given {@code CompletionStage}. 95 * 96 * <p> Might be useful both for producers and consumers of {@code 97 * CompletionStage}s. 98 * 99 * <p> Producers are protected from possible uncontrolled modifications 100 * (cancellation, completion, obtrusion, etc.) as well as from executing 101 * unknown potentially lengthy or faulty dependants in the given {@code 102 * CompletionStage}'s default execution facility or synchronously. 103 * 104 * <p> Consumers are protected from some of the aspects of misbehaving 105 * implementations (e.g. accepting results, applying functions, running 106 * tasks, etc. more than once or escape of a reference to their private 107 * executor, etc.) by providing a reliable proxy they use instead. 108 * 109 * @param src 110 * the {@code CompletionStage} to make a copy from 111 * @param executor 112 * the executor used to propagate the completion 113 * @param <T> 114 * the type of the {@code CompletionStage}'s result 115 * 116 * @return a copy of the given stage 117 */ 118 public static <T> MinimalFuture<T> copy(CompletionStage<T> src, 119 Executor executor) { 120 MinimalFuture<T> copy = new MinimalFuture<>(); 121 BiConsumer<T, Throwable> relay = 122 (result, error) -> { 123 if (error != null) { 124 copy.completeExceptionally(error); 125 } else { 126 copy.complete(result); 127 } 128 }; 129 130 if (src.getClass() == CompletableFuture.class) { 131 // No subclasses! Strictly genuine CompletableFuture. 132 src.whenCompleteAsync(relay, executor); 133 return copy; 134 } else { 135 // Don't give our executor away to an unknown CS! 136 src.whenComplete(relay); 137 return (MinimalFuture<T>) 138 copy.thenApplyAsync(Function.identity(), executor); 139 } 140 } 141 142 public static <U> MinimalFuture<U> newMinimalFuture() { 143 return new MinimalFuture<>(); 144 } 145 146 @Override 147 public void obtrudeValue(T value) { 148 throw new UnsupportedOperationException(); 149 } 150 151 @Override 152 public void obtrudeException(Throwable ex) { 153 throw new UnsupportedOperationException(); 154 } 155 156 @Override 157 public String toString() { 158 return super.toString() + " (id=" + id +")"; 159 } 160 161 public static <U> MinimalFuture<U> of(CompletionStage<U> stage) { 162 MinimalFuture<U> cf = newMinimalFuture(); 163 stage.whenComplete((r,t) -> complete(cf, r, t)); 164 return cf; 165 } 166 167 private static <U> void complete(CompletableFuture<U> cf, U result, Throwable t) { 168 if (t == null) { 169 cf.complete(result); 170 } else { 171 cf.completeExceptionally(t); 172 } 173 } 174 }