diff --git a/common/src/main/java/io/netty/util/concurrent/DefaultPromise.java b/common/src/main/java/io/netty/util/concurrent/DefaultPromise.java index 6facc2fe71..2ff8c68275 100644 --- a/common/src/main/java/io/netty/util/concurrent/DefaultPromise.java +++ b/common/src/main/java/io/netty/util/concurrent/DefaultPromise.java @@ -16,7 +16,6 @@ package io.netty.util.concurrent; import io.netty.util.internal.InternalThreadLocalMap; -import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.StringUtil; import io.netty.util.internal.SystemPropertyUtil; import io.netty.util.internal.ThrowableUtil; @@ -25,7 +24,9 @@ import io.netty.util.internal.logging.InternalLoggerFactory; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import static java.util.Objects.requireNonNull; @@ -145,15 +146,21 @@ public class DefaultPromise implements Promise { @Override public Throwable cause() { - Object result = this.result; - if (result != CANCELLATION_CAUSE_HOLDER) { - return (result instanceof CauseHolder) ? ((CauseHolder) result).cause : null; + return cause0(result); + } + + private Throwable cause0(Object result) { + if (!(result instanceof CauseHolder)) { + return null; } - CancellationException ce = new LeanCancellationException(); - if (RESULT_UPDATER.compareAndSet(this, CANCELLATION_CAUSE_HOLDER, new CauseHolder(ce))) { - return ce; + if (result == CANCELLATION_CAUSE_HOLDER) { + CancellationException ce = new LeanCancellationException(); + if (RESULT_UPDATER.compareAndSet(this, CANCELLATION_CAUSE_HOLDER, new CauseHolder(ce))) { + return ce; + } + result = this.result; } - return ((CauseHolder) this.result).cause; + return ((CauseHolder) result).cause; } @Override @@ -313,6 +320,50 @@ public class DefaultPromise implements Promise { return (V) result; } + @SuppressWarnings("unchecked") + @Override + public V get() throws InterruptedException, ExecutionException { + Object result = this.result; + if (!isDone0(result)) { + await(); + result = this.result; + } + if (result == SUCCESS || result == UNCANCELLABLE) { + return null; + } + Throwable cause = cause0(result); + if (cause == null) { + return (V) result; + } + if (cause instanceof CancellationException) { + throw (CancellationException) cause; + } + throw new ExecutionException(cause); + } + + @SuppressWarnings("unchecked") + @Override + public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + Object result = this.result; + if (!isDone0(result)) { + if (!await(timeout, unit)) { + throw new TimeoutException(); + } + result = this.result; + } + if (result == SUCCESS || result == UNCANCELLABLE) { + return null; + } + Throwable cause = cause0(result); + if (cause == null) { + return (V) result; + } + if (cause instanceof CancellationException) { + throw (CancellationException) cause; + } + throw new ExecutionException(cause); + } + /** * {@inheritDoc} *