AbstractFuture should not wrap CancellationException

Motivation:
AbstractFuture currently wraps CancellationException in a ExecutionException. However the interface of Future says that this exception should be directly thrown.

Modifications:
- Throw CancellationException from AbstractFuture.get

Result:
Interface contract for CancellationException is honored in AbstractFuture.
This commit is contained in:
Scott Mitchell 2015-12-07 18:23:03 -08:00
parent 1f6b957377
commit 32933821bb
2 changed files with 25 additions and 0 deletions

View File

@ -15,6 +15,7 @@
*/ */
package io.netty.util.concurrent; package io.netty.util.concurrent;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@ -34,6 +35,9 @@ public abstract class AbstractFuture<V> implements Future<V> {
if (cause == null) { if (cause == null) {
return getNow(); return getNow();
} }
if (cause instanceof CancellationException) {
throw (CancellationException) cause;
}
throw new ExecutionException(cause); throw new ExecutionException(cause);
} }
@ -44,6 +48,9 @@ public abstract class AbstractFuture<V> implements Future<V> {
if (cause == null) { if (cause == null) {
return getNow(); return getNow();
} }
if (cause instanceof CancellationException) {
throw (CancellationException) cause;
}
throw new ExecutionException(cause); throw new ExecutionException(cause);
} }
throw new TimeoutException(); throw new TimeoutException();

View File

@ -19,10 +19,13 @@ package io.netty.util.concurrent;
import org.junit.Test; import org.junit.Test;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
@ -34,6 +37,21 @@ import static org.junit.Assert.assertTrue;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class DefaultPromiseTest { public class DefaultPromiseTest {
@Test(expected = CancellationException.class)
public void testCancellationExceptionIsThrownWhenBlockingGet() throws InterruptedException, ExecutionException {
final Promise<Void> promise = new DefaultPromise<Void>(ImmediateEventExecutor.INSTANCE);
promise.cancel(false);
promise.get();
}
@Test(expected = CancellationException.class)
public void testCancellationExceptionIsThrownWhenBlockingGetWithTimeout() throws InterruptedException,
ExecutionException, TimeoutException {
final Promise<Void> promise = new DefaultPromise<Void>(ImmediateEventExecutor.INSTANCE);
promise.cancel(false);
promise.get(1, TimeUnit.SECONDS);
}
@Test @Test
public void testNoStackOverflowErrorWithImmediateEventExecutorA() throws Exception { public void testNoStackOverflowErrorWithImmediateEventExecutorA() throws Exception {
final Promise<Void>[] p = new DefaultPromise[128]; final Promise<Void>[] p = new DefaultPromise[128];