--- jsr166/src/jsr166e/CompletableFuture.java 2013/01/02 17:37:14 1.2 +++ jsr166/src/jsr166e/CompletableFuture.java 2013/02/06 07:04:48 1.9 @@ -83,9 +83,9 @@ public class CompletableFuture implem /* * Overview: * - * 1. Non-nullness of field result (set via CAS) indicates - * done. An AltResult is used to box null as a result, as well as - * to hold exceptions. Using a single field makes completion fast + * 1. Non-nullness of field result (set via CAS) indicates done. + * An AltResult is used to box null as a result, as well as to + * hold exceptions. Using a single field makes completion fast * and simple to detect and trigger, at the expense of a lot of * encoding and decoding that infiltrates many methods. One minor * simplification relies on the (static) NIL (to box null results) @@ -287,7 +287,7 @@ public class CompletableFuture implem else if (q.thread != null && result == null) { try { ForkJoinPool.managedBlock(q); - } catch(InterruptedException ex){ + } catch (InterruptedException ex) { q.interruptControl = -1; } } @@ -320,7 +320,7 @@ public class CompletableFuture implem if (nanos <= 0L) throw new TimeoutException(); long d = System.nanoTime() + nanos; - q = new WaitNode(true, nanos, d == 0L? 1L : d); // avoid 0 + q = new WaitNode(true, nanos, d == 0L ? 1L : d); // avoid 0 } else if (!queued) queued = UNSAFE.compareAndSwapObject(this, WAITERS, @@ -338,7 +338,7 @@ public class CompletableFuture implem else if (q.thread != null && result == null) { try { ForkJoinPool.managedBlock(q); - } catch(InterruptedException ex){ + } catch (InterruptedException ex) { q.interruptControl = -1; } } @@ -388,7 +388,7 @@ public class CompletableFuture implem } /** Base class can act as either FJ or plain Runnable */ - static abstract class Async extends ForkJoinTask + abstract static class Async extends ForkJoinTask implements Runnable, AsynchronousCompletionTask { public final Void getRawResult() { return null; } public final void setRawResult(Void v) { } @@ -557,7 +557,7 @@ public class CompletableFuture implem } // Opportunistically subclass AtomicInteger to use compareAndSet to claim. - static abstract class Completion extends AtomicInteger implements Runnable { + abstract static class Completion extends AtomicInteger implements Runnable { } static final class ApplyCompletion extends Completion { @@ -2449,10 +2449,10 @@ public class CompletableFuture implem * then the returned CompletableFuture also does so, with a * CompletionException holding this exception as its cause. * - * @param fn the function returning a new CompletableFuture. + * @param fn the function returning a new CompletableFuture * @return the CompletableFuture, that {@code isDone()} upon * return if completed by the given function, or an exception - * occurs. + * occurs */ public CompletableFuture thenCompose(Fun> fn) { @@ -2644,7 +2644,7 @@ public class CompletableFuture implem * completed. This method is designed for use only in error * recovery actions, and even in such situations may result in * ongoing dependent completions using established versus - * overwritten values. + * overwritten outcomes. * * @param value the completion value */ @@ -2653,6 +2653,22 @@ public class CompletableFuture implem postComplete(); } + /** + * Forcibly causes subsequent invocations of method {@link #get()} + * and related methods to throw the given exception, whether or + * not already completed. This method is designed for use only in + * recovery actions, and even in such situations may result in + * ongoing dependent completions using established versus + * overwritten outcomes. + * + * @param ex the exception + */ + public void obtrudeException(Throwable ex) { + if (ex == null) throw new NullPointerException(); + result = new AltResult(ex); + postComplete(); + } + // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE; private static final long RESULT; @@ -2684,22 +2700,23 @@ public class CompletableFuture implem private static sun.misc.Unsafe getUnsafe() { try { return sun.misc.Unsafe.getUnsafe(); - } catch (SecurityException se) { - try { - return java.security.AccessController.doPrivileged - (new java.security - .PrivilegedExceptionAction() { - public sun.misc.Unsafe run() throws Exception { - java.lang.reflect.Field f = sun.misc - .Unsafe.class.getDeclaredField("theUnsafe"); - f.setAccessible(true); - return (sun.misc.Unsafe) f.get(null); - }}); - } catch (java.security.PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } + } catch (SecurityException tryReflectionInstead) {} + try { + return java.security.AccessController.doPrivileged + (new java.security.PrivilegedExceptionAction() { + public sun.misc.Unsafe run() throws Exception { + Class k = sun.misc.Unsafe.class; + for (java.lang.reflect.Field f : k.getDeclaredFields()) { + f.setAccessible(true); + Object x = f.get(null); + if (k.isInstance(x)) + return k.cast(x); + } + throw new NoSuchFieldError("the Unsafe"); + }}); + } catch (java.security.PrivilegedActionException e) { + throw new RuntimeException("Could not initialize intrinsics", + e.getCause()); } } - }