diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java index aa219e2658..18c10647dd 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java @@ -268,7 +268,7 @@ public abstract class WebSocketClientHandshaker { promise.setFailure(future.cause()); } }); - return promise; + return promise.asFuture(); } /** @@ -432,7 +432,7 @@ public abstract class WebSocketClientHandshaker { } catch (Throwable cause) { promise.setFailure(cause); } - return promise; + return promise.asFuture(); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandshakeHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandshakeHandler.java index 6aa4e49258..055cde8b46 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandshakeHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandshakeHandler.java @@ -117,7 +117,7 @@ class WebSocketClientProtocolHandshakeHandler implements ChannelHandler { }, handshakeTimeoutMillis, TimeUnit.MILLISECONDS); // Cancel the handshake timeout when handshake is finished. - localHandshakePromise.addListener(f -> timeoutFuture.cancel(false)); + localHandshakePromise.asFuture().addListener(f -> timeoutFuture.cancel(false)); } /** @@ -126,6 +126,6 @@ class WebSocketClientProtocolHandshakeHandler implements ChannelHandler { * @return current handshake future */ Future getHandshakeFuture() { - return handshakePromise; + return handshakePromise.asFuture(); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java index 54d0bdb593..dab9bdc726 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java @@ -85,13 +85,14 @@ abstract class WebSocketProtocolHandler extends MessageToMessageDecoder future = closeSent == null ? write(ctx, new CloseWebSocketFrame(closeStatus)) : closeSent; + final Future future = closeSent == null ? + write(ctx, new CloseWebSocketFrame(closeStatus)) : closeSent.asFuture(); flush(ctx); applyCloseSentTimeout(ctx); Promise promise = ctx.newPromise(); future.addListener(f -> ctx.close().cascadeTo(promise)); - return promise; + return promise.asFuture(); } @Override @@ -104,7 +105,7 @@ abstract class WebSocketProtocolHandler extends MessageToMessageDecoder promise = ctx.newPromise(); closeSent(promise); ctx.write(msg).cascadeTo(closeSent); - return promise; + return promise.asFuture(); } return ctx.write(msg); } @@ -124,7 +125,7 @@ abstract class WebSocketProtocolHandler extends MessageToMessageDecoder timeoutTask.cancel(false)); + closeSent.asFuture().addListener(future -> timeoutTask.cancel(false)); } /** diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java index 61261610b0..7cac8e8340 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java @@ -311,7 +311,7 @@ public abstract class WebSocketServerHandshaker { } catch (Throwable cause) { promise.setFailure(cause); } - return promise; + return promise.asFuture(); } /** diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandshakeHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandshakeHandler.java index 2afa09e8cd..5c35b39784 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandshakeHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandshakeHandler.java @@ -27,7 +27,6 @@ import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler.ServerHandshakeStateEvent; import io.netty.handler.ssl.SslHandler; import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.FutureListener; import io.netty.util.concurrent.Promise; import java.util.Objects; @@ -158,6 +157,6 @@ class WebSocketServerProtocolHandshakeHandler implements ChannelHandler { }, handshakeTimeoutMillis, TimeUnit.MILLISECONDS); // Cancel the handshake timeout when handshake is finished. - localHandshakePromise.addListener(f -> timeoutFuture.cancel(false)); + localHandshakePromise.asFuture().addListener(f -> timeoutFuture.cancel(false)); } } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerUpgradeHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerUpgradeHandlerTest.java index 507e05c8c9..7bc3a329e3 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerUpgradeHandlerTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerUpgradeHandlerTest.java @@ -101,8 +101,8 @@ public class HttpServerUpgradeHandlerTest { writeUpgradeMessage = true; Promise promise = ctx.newPromise(); ctx.channel().executor().execute(() -> ctx.write(msg).cascadeTo(promise)); - promise.addListener(f -> writeFlushed = true); - return promise; + Future future = promise.asFuture(); + return future.addListener(f -> writeFlushed = true); } }; diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandlerTest.java index b361ff98d9..b88c460e0a 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandlerTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandlerTest.java @@ -158,7 +158,7 @@ public class WebSocketProtocolHandlerTest { EmbeddedChannel channel = new EmbeddedChannel(new ChannelHandler() { @Override public Future write(ChannelHandlerContext ctx, Object msg) { - Future future = ctx.newPromise(); + Future future = ctx.newPromise().asFuture(); ref.set(future); ReferenceCountUtil.release(msg); return future; diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/AbstractHttp2StreamChannel.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/AbstractHttp2StreamChannel.java index 22e3602d33..7b99ab9bb5 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/AbstractHttp2StreamChannel.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/AbstractHttp2StreamChannel.java @@ -334,7 +334,7 @@ abstract class AbstractHttp2StreamChannel extends DefaultAttributeMap implements @Override public Future closeFuture() { - return closePromise; + return closePromise.asFuture(); } @Override @@ -514,7 +514,7 @@ abstract class AbstractHttp2StreamChannel extends DefaultAttributeMap implements promise.setSuccess(null); } else { // This means close() was called before so we just register a listener and return - closePromise.addListener(promise, (p, future) -> p.setSuccess(null)); + closeFuture().addListener(promise, (p, future) -> p.setSuccess(null)); } return; } diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/CompressorHttp2ConnectionEncoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/CompressorHttp2ConnectionEncoder.java index 4436bd872b..545a7366f1 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/CompressorHttp2ConnectionEncoder.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/CompressorHttp2ConnectionEncoder.java @@ -187,7 +187,7 @@ public class CompressorHttp2ConnectionEncoder extends DecoratingHttp2ConnectionE buf = nextBuf; } combiner.finish(promise); - return promise; + return promise.asFuture(); } catch (Throwable cause) { return ctx.newFailedFuture(cause); } finally { diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Connection.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Connection.java index 82d03cc93c..91e28cf03e 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Connection.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Connection.java @@ -123,7 +123,7 @@ public class DefaultHttp2Connection implements Http2Connection { if (closePromise == promise) { // Do nothing } else { - closePromise.addListener(new UnaryPromiseNotifier<>(promise)); + closePromise.asFuture().addListener(new UnaryPromiseNotifier<>(promise)); } } else { closePromise = promise; diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionEncoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionEncoder.java index 63b9d837cc..bdba4f1383 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionEncoder.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionEncoder.java @@ -143,7 +143,7 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder, Ht // Hand control of the frame to the flow controller. flowController().addFlowControlled(stream, new FlowControlledData(stream, data, padding, endOfStream, promise, ctx.channel())); - return promise; + return promise.asFuture(); } @Override @@ -266,7 +266,7 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder, Ht flowController.addFlowControlled(stream, new FlowControlledHeaders(stream, headers, hasPriority, streamDependency, weight, exclusive, padding, true, promise)); - return promise; + return promise.asFuture(); } } catch (Throwable t) { lifecycleManager.onError(ctx, true, t); @@ -479,7 +479,7 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder, Ht // queue and it is not end of stream yet. Just complete their promises by getting the buffer // corresponding to 0 bytes and writing it to the channel (to preserve notification order). Promise writePromise = ctx.newPromise(); - writePromise.addListener(this); + writePromise.asFuture().addListener(this); ctx.write(queue.remove(0, writePromise)).cascadeTo(writePromise); } return; @@ -493,7 +493,7 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder, Ht // Determine how much data to write. int writableData = min(queuedData, allowedBytes); Promise writePromise = ctx.newPromise(); - writePromise.addListener(this); + writePromise.asFuture().addListener(this); ByteBuf toWrite = queue.remove(writableData, writePromise); dataSize = queue.readableBytes(); @@ -572,7 +572,7 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder, Ht boolean isInformational = validateHeadersSentState(stream, headers, connection.isServer(), endOfStream); // The code is currently requiring adding this listener before writing, in order to call onError() before // closeStreamLocal(). - promise.addListener(this); + promise.asFuture().addListener(this); Future f = sendHeaders(frameWriter, ctx, stream.id(), headers, hasPriority, streamDependency, weight, exclusive, padding, endOfStream); @@ -612,7 +612,7 @@ public class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder, Ht @Override public void writeComplete() { if (endOfStream) { - lifecycleManager.closeStreamLocal(stream, promise); + lifecycleManager.closeStreamLocal(stream, promise.asFuture()); } } diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2CodecUtil.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2CodecUtil.java index 7f1847f10a..43e5fec1f4 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2CodecUtil.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2CodecUtil.java @@ -23,6 +23,7 @@ import io.netty.handler.ssl.ApplicationProtocolNames; import io.netty.util.AsciiString; import io.netty.util.concurrent.DefaultPromise; import io.netty.util.concurrent.EventExecutor; +import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Promise; import io.netty.util.internal.UnstableApi; @@ -284,13 +285,13 @@ public final class Http2CodecUtil { /** * Signify that no more {@link #newPromise()} allocations will be made. * The aggregation can not be successful until this method is called. - * @return The promise that is the aggregation of all promises allocated with {@link #newPromise()}. + * @return The {@link Future} that is the aggregation of all promises allocated with {@link #newPromise()}. */ - public Promise doneAllocatingPromises() { + public Future doneAllocatingPromises() { if (!doneAllocating) { doneAllocating = true; if (doneCount == expectedCount || expectedCount == 0) { - return setPromise(); + return setPromise().asFuture(); } } return this; @@ -323,7 +324,7 @@ public final class Http2CodecUtil { ++doneCount; setAggregateFailure(cause); if (allPromisesDone()) { - return setPromise(); + setPromise(); } } return this; @@ -369,11 +370,12 @@ public final class Http2CodecUtil { private Promise setPromise() { if (aggregateFailure == null) { promise.setSuccess(null); - return super.setSuccess(null); + super.setSuccess(null); } else { promise.setFailure(aggregateFailure); - return super.setFailure(aggregateFailure); + super.setFailure(aggregateFailure); } + return this; } private boolean tryPromise() { diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java index 0411a8e24c..cde8ff15b0 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java @@ -454,7 +454,7 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http ctx.flush(); Promise promise = ctx.newPromise(); doGracefulShutdown(ctx, f, promise); - return promise; + return promise.asFuture(); } private FutureListener newClosingChannelFutureListener( diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrap.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrap.java index a27b660960..f59146ac61 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrap.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrap.java @@ -128,7 +128,7 @@ public final class Http2StreamChannelBootstrap { } catch (Throwable cause) { promise.setFailure(cause); } - return promise; + return promise.asFuture(); } @SuppressWarnings("deprecation") @@ -189,7 +189,7 @@ public final class Http2StreamChannelBootstrap { if (future1.isSuccess()) { promise.setSuccess(streamChannel); } else if (future1.isCancelled()) { - promise.cancel(false); + promise.cancel(); } else { if (streamChannel.isRegistered()) { streamChannel.close(); diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpToHttp2ConnectionHandler.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpToHttp2ConnectionHandler.java index 002d57580a..4ffa0389ac 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpToHttp2ConnectionHandler.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpToHttp2ConnectionHandler.java @@ -144,7 +144,7 @@ public class HttpToHttp2ConnectionHandler extends Http2ConnectionHandler { } promiseAggregator.doneAllocatingPromises(); } - return promise; + return promise.asFuture(); } private static Future writeHeaders(ChannelHandlerContext ctx, Http2ConnectionEncoder encoder, int streamId, diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/StreamBufferingEncoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/StreamBufferingEncoder.java index 689d54aa5b..43feb27a75 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/StreamBufferingEncoder.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/StreamBufferingEncoder.java @@ -182,7 +182,7 @@ public class StreamBufferingEncoder extends DecoratingHttp2ConnectionEncoder { pendingStream.frames.add(new HeadersFrame(headers, streamDependency, weight, exclusive, padding, endOfStream, promise)); - return promise; + return promise.asFuture(); } @Override @@ -215,7 +215,7 @@ public class StreamBufferingEncoder extends DecoratingHttp2ConnectionEncoder { if (pendingStream != null) { Promise promise = ctx.newPromise(); pendingStream.frames.add(new DataFrame(data, padding, endOfStream, promise)); - return promise; + return promise.asFuture(); } else { ReferenceCountUtil.safeRelease(data); return ctx.newFailedFuture(connectionError(PROTOCOL_ERROR, "Stream does not exist %d", streamId)); diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionTest.java index 126a2e9faf..e40bdf7f71 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2ConnectionTest.java @@ -155,9 +155,10 @@ public class DefaultHttp2ConnectionTest { final Promise promise = group.next().newPromise(); final CountDownLatch latch = new CountDownLatch(client.numActiveStreams()); client.forEachActiveStream(stream -> { - client.close(promise.addListener(future -> { + promise.asFuture().addListener(future -> { latch.countDown(); - })); + }); + client.close(promise); return true; }); assertTrue(latch.await(5, TimeUnit.SECONDS)); @@ -183,9 +184,10 @@ public class DefaultHttp2ConnectionTest { return true; }); } catch (Http2Exception ignored) { - client.close(promise.addListener(future -> { + promise.asFuture().addListener(future -> { latch.countDown(); - })); + }); + client.close(promise); } assertTrue(latch.await(5, TimeUnit.SECONDS)); } @@ -632,9 +634,10 @@ public class DefaultHttp2ConnectionTest { private void testRemoveAllStreams() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); final Promise promise = group.next().newPromise(); - client.close(promise.addListener(future -> { + promise.asFuture().addListener(future -> { latch.countDown(); - })); + }); + client.close(promise); assertTrue(latch.await(5, TimeUnit.SECONDS)); } diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionHandlerTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionHandlerTest.java index 26885a8db2..a11493e2bb 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionHandlerTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionHandlerTest.java @@ -54,8 +54,8 @@ import static io.netty.handler.codec.http2.Http2Stream.State.CLOSED; import static io.netty.handler.codec.http2.Http2Stream.State.IDLE; import static io.netty.util.CharsetUtil.US_ASCII; import static io.netty.util.CharsetUtil.UTF_8; +import static io.netty.util.concurrent.DefaultPromise.newSuccessfulPromise; import static java.util.concurrent.TimeUnit.SECONDS; -import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertSame; @@ -194,7 +194,7 @@ public class Http2ConnectionHandlerTest { when(ctx.newFailedFuture(any(Throwable.class))) .thenAnswer(invocationOnMock -> DefaultPromise.newFailedPromise(executor, invocationOnMock.getArgument(0))); - when(ctx.newSucceededFuture()).thenReturn(DefaultPromise.newSuccessfulPromise(executor, null)); + when(ctx.newSucceededFuture()).thenReturn(newSuccessfulPromise(executor, (Void) null).asFuture()); when(ctx.newPromise()).thenReturn(promise); when(ctx.write(any())).thenReturn(future); when(ctx.executor()).thenReturn(executor); @@ -204,9 +204,9 @@ public class Http2ConnectionHandlerTest { return null; }).when(ctx).fireChannelRead(any()); doAnswer((Answer>) in -> - DefaultPromise.newSuccessfulPromise(executor, null)).when(ctx).write(any()); + newSuccessfulPromise(executor, (Void) null).asFuture()).when(ctx).write(any()); doAnswer((Answer>) in -> - DefaultPromise.newSuccessfulPromise(executor, null)).when(ctx).close(); + newSuccessfulPromise(executor, (Void) null).asFuture()).when(ctx).close(); } private Http2ConnectionHandler newHandler() throws Exception { diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java index 5b33a9e3dd..9f405c427c 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java @@ -150,8 +150,8 @@ public class Http2ConnectionRoundtripTest { doAnswer(invocationOnMock -> { ChannelHandlerContext ctx = invocationOnMock.getArgument(0); http2Server.encoder().writeHeaders(ctx, - (Integer) invocationOnMock.getArgument(1), - (Http2Headers) invocationOnMock.getArgument(2), + invocationOnMock.getArgument(1), + invocationOnMock.getArgument(2), 0, false); http2Server.flush(ctx); @@ -615,7 +615,7 @@ public class Http2ConnectionRoundtripTest { ExecutionException e = assertThrows(ExecutionException.class, new Executable() { @Override public void execute() throws Throwable { - promise.get(); + promise.asFuture().get(); } }); assertThat(e.getCause(), is(instanceOf(IllegalReferenceCountException.class))); @@ -668,11 +668,11 @@ public class Http2ConnectionRoundtripTest { ExecutionException e = assertThrows(ExecutionException.class, new Executable() { @Override public void execute() throws Throwable { - dataPromise.get(); + dataPromise.asFuture().get(); } }); assertThat(e.getCause(), is(instanceOf(IllegalStateException.class))); - assertPromise.sync(); + assertPromise.asFuture().sync(); } @Test @@ -1094,10 +1094,6 @@ public class Http2ConnectionRoundtripTest { return ctx().newPromise(); } - private Promise serverNewPromise() { - return serverCtx().newPromise(); - } - private static Http2Headers dummyHeaders() { return new DefaultHttp2Headers(false).method(new AsciiString("GET")).scheme(new AsciiString("https")) .authority(new AsciiString("example.org")).path(new AsciiString("/some/path/resource2")) diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ControlFrameLimitEncoderTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ControlFrameLimitEncoderTest.java index 256f22c2e4..ad4892b944 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ControlFrameLimitEncoderTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ControlFrameLimitEncoderTest.java @@ -100,23 +100,23 @@ public class Http2ControlFrameLimitEncoderTest { when(frameSizePolicy.maxFrameSize()).thenReturn(DEFAULT_MAX_FRAME_SIZE); when(writer.writeRstStream(eq(ctx), anyInt(), anyLong())) - .thenAnswer((Answer>) invocationOnMock -> handlePromise()); + .thenAnswer((Answer>) invocationOnMock -> handlePromise().asFuture()); when(writer.writeSettingsAck(any(ChannelHandlerContext.class))) - .thenAnswer((Answer>) invocationOnMock -> handlePromise()); + .thenAnswer((Answer>) invocationOnMock -> handlePromise().asFuture()); when(writer.writePing(any(ChannelHandlerContext.class), anyBoolean(), anyLong())) .thenAnswer((Answer>) invocationOnMock -> { Promise promise = handlePromise(); if (invocationOnMock.getArgument(1) == Boolean.FALSE) { promise.trySuccess(null); } - return promise; + return promise.asFuture(); }); when(writer.writeGoAway(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class))) .thenAnswer((Answer>) invocationOnMock -> { ReferenceCountUtil.release(invocationOnMock.getArgument(3)); Promise promise = ImmediateEventExecutor.INSTANCE.newPromise(); goAwayPromises.offer(promise); - return promise; + return promise.asFuture(); }); Http2Connection connection = new DefaultHttp2Connection(false); connection.remote().flowController(new DefaultHttp2RemoteFlowController(connection)); @@ -136,8 +136,8 @@ public class Http2ControlFrameLimitEncoderTest { when(ctx.alloc()).thenReturn(UnpooledByteBufAllocator.DEFAULT); when(channel.alloc()).thenReturn(UnpooledByteBufAllocator.DEFAULT); when(executor.inEventLoop()).thenReturn(true); - doAnswer((Answer) invocation -> newPromise()).when(ctx).newPromise(); - doAnswer((Answer) invocation -> + doAnswer((Answer>) invocation -> newPromise()).when(ctx).newPromise(); + doAnswer((Answer>) invocation -> ImmediateEventExecutor.INSTANCE.newFailedFuture(invocation.getArgument(0))) .when(ctx).newFailedFuture(any(Throwable.class)); @@ -164,7 +164,7 @@ public class Http2ControlFrameLimitEncoderTest { } @AfterEach - public void teardown() { + public void tearDown() { // Close and release any buffered frames. encoder.close(); diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameCodecTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameCodecTest.java index ab996a09aa..78db1a0ca6 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameCodecTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameCodecTest.java @@ -626,7 +626,7 @@ public class Http2FrameCodecTest { Future f = channel.writeAndFlush(new DefaultHttp2DataFrame(data).stream(stream)); assertTrue(f.isSuccess()); - listenerExecuted.syncUninterruptibly(); + listenerExecuted.asFuture().syncUninterruptibly(); assertTrue(listenerExecuted.isSuccess()); } diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameRoundtripTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameRoundtripTest.java index dd1d24fad1..c0f7adba59 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameRoundtripTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameRoundtripTest.java @@ -99,7 +99,7 @@ public class Http2FrameRoundtripTest { when(ctx.executor()).thenReturn(executor); when(ctx.channel()).thenReturn(channel); doAnswer((Answer>) in -> - DefaultPromise.newSuccessfulPromise(executor, null)).when(ctx).write(any()); + DefaultPromise.newSuccessfulPromise(executor, (Void) null).asFuture()).when(ctx).write(any()); doAnswer((Answer) in -> Unpooled.buffer()).when(alloc).buffer(); doAnswer((Answer) in -> Unpooled.buffer((Integer) in.getArguments()[0])).when(alloc).buffer(anyInt()); doAnswer((Answer>) invocation -> @@ -110,7 +110,7 @@ public class Http2FrameRoundtripTest { } @AfterEach - public void teardown() { + public void tearDown() { try { // Release all of the buffers. for (ByteBuf buf : needReleasing) { diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2MultiplexTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2MultiplexTest.java index 0a5c1bfee7..9085b4ba19 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2MultiplexTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2MultiplexTest.java @@ -72,7 +72,6 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@SuppressWarnings("unchecked") public abstract class Http2MultiplexTest { private final Http2Headers request = new DefaultHttp2Headers() .method(HttpMethod.GET.asciiName()).scheme(HttpScheme.HTTPS.name()) @@ -729,7 +728,7 @@ public abstract class Http2MultiplexTest { // Create a promise before actually doing the close, because otherwise we would be adding a listener to a future // that is already completed because we are using EmbeddedChannel which executes code in the JUnit thread. Promise p = childChannel.newPromise(); - p.addListener(childChannel, (channel, future) -> { + p.asFuture().addListener(childChannel, (channel, future) -> { channelOpen.set(channel.isOpen()); channelActive.set(channel.isActive()); }); @@ -972,7 +971,7 @@ public abstract class Http2MultiplexTest { Promise promise = childChannel.newPromise(); childChannel.unsafe().close(promise); - promise.syncUninterruptibly(); + promise.asFuture().syncUninterruptibly(); childChannel.closeFuture().syncUninterruptibly(); } diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrapTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrapTest.java index 0ba2ba6acb..94756e88ad 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrapTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2StreamChannelBootstrapTest.java @@ -101,10 +101,10 @@ public class Http2StreamChannelBootstrapTest { ExecutionException exception = assertThrows(ExecutionException.class, new Executable() { @Override public void execute() throws Throwable { - promise.get(3, SECONDS); + promise.asFuture().get(3, SECONDS); } }); - assertThat(exception.getCause(), IsInstanceOf.instanceOf(ClosedChannelException.class)); + assertThat(exception.getCause(), IsInstanceOf.instanceOf(ClosedChannelException.class)); } finally { safeClose(clientChannel); safeClose(serverConnectedChannel); diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/StreamBufferingEncoderTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/StreamBufferingEncoderTest.java index 9c1897761b..46439be6ca 100644 --- a/codec-http2/src/test/java/io/netty/handler/codec/http2/StreamBufferingEncoderTest.java +++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/StreamBufferingEncoderTest.java @@ -25,7 +25,6 @@ import io.netty.channel.ChannelMetadata; import io.netty.channel.DefaultMessageSizeEstimator; import io.netty.handler.codec.http2.StreamBufferingEncoder.Http2GoAwayException; import io.netty.util.ReferenceCountUtil; -import io.netty.util.concurrent.DefaultPromise; import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.ImmediateEventExecutor; @@ -545,9 +544,7 @@ public class StreamBufferingEncoderTest { ReferenceCountUtil.safeRelease(a); } - Promise future = newPromise(); - future.setSuccess(null); - return future; + return ImmediateEventExecutor.INSTANCE.newSucceededFuture(null); }; } @@ -557,16 +554,16 @@ public class StreamBufferingEncoderTest { public Future answer(InvocationOnMock invocation) throws Throwable { for (Object a : invocation.getArguments()) { if (a instanceof Promise) { - return (Future) a; + return ((Promise) a).asFuture(); } } - return newPromise(); + return newPromise().asFuture(); } }; } private static Promise newPromise() { - return new DefaultPromise(ImmediateEventExecutor.INSTANCE); + return ImmediateEventExecutor.INSTANCE.newPromise(); } private static ByteBuf data() { diff --git a/codec/src/main/java/io/netty/handler/codec/MessageToMessageEncoder.java b/codec/src/main/java/io/netty/handler/codec/MessageToMessageEncoder.java index b825b831c2..ded2114c8d 100644 --- a/codec/src/main/java/io/netty/handler/codec/MessageToMessageEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/MessageToMessageEncoder.java @@ -106,7 +106,7 @@ public abstract class MessageToMessageEncoder extends ChannelHandlerAdapter { writePromiseCombiner(ctx, out, promise); } } - return promise; + return promise.asFuture(); } else { return ctx.write(msg); } diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Encoder.java b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Encoder.java index c3d0ec47c2..6523436d85 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Encoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Encoder.java @@ -183,7 +183,7 @@ public class Bzip2Encoder extends MessageToByteEncoder { Future f = finishEncode(ctx()); f.cascadeTo(promise); }); - return promise; + return promise.asFuture(); } } @@ -198,7 +198,7 @@ public class Bzip2Encoder extends MessageToByteEncoder { // Ensure the channel is closed even if the write operation completes in time. ctx.executor().schedule(() -> ctx.close().cascadeTo(promise), 10, TimeUnit.SECONDS); // FIXME: Magic number - return promise; + return promise.asFuture(); } private Future finishEncode(final ChannelHandlerContext ctx) { diff --git a/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java b/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java index 168a024bd7..eee877b127 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java @@ -165,7 +165,7 @@ public class JdkZlibEncoder extends ZlibEncoder { Future f = finishEncode(ctx()); f.cascadeTo(p); }); - return p; + return p.asFuture(); } } @@ -265,7 +265,7 @@ public class JdkZlibEncoder extends ZlibEncoder { // Ensure the channel is closed even if the write operation completes in time. ctx.executor().schedule(() -> ctx.close().cascadeTo(promise), 10, TimeUnit.SECONDS); // FIXME: Magic number - return promise; + return promise.asFuture(); } private Future finishEncode(final ChannelHandlerContext ctx) { diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Lz4FrameEncoder.java b/codec/src/main/java/io/netty/handler/codec/compression/Lz4FrameEncoder.java index adc1741912..5b63aeee78 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/Lz4FrameEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/Lz4FrameEncoder.java @@ -349,7 +349,7 @@ public class Lz4FrameEncoder extends MessageToByteEncoder { Future f = finishEncode(ctx()); f.cascadeTo(promise); }); - return promise; + return promise.asFuture(); } } @@ -364,7 +364,7 @@ public class Lz4FrameEncoder extends MessageToByteEncoder { // Ensure the channel is closed even if the write operation completes in time. ctx.executor().schedule(() -> ctx.close().cascadeTo(promise), 10, TimeUnit.SECONDS); // FIXME: Magic number - return promise; + return promise.asFuture(); } private ChannelHandlerContext ctx() { diff --git a/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java index 259b0c8f4e..b08d7d5943 100644 --- a/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java +++ b/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java @@ -36,7 +36,7 @@ public abstract class AbstractEventExecutor extends AbstractExecutorService impl static final long DEFAULT_SHUTDOWN_TIMEOUT = 15; private final Collection selfCollection = Collections.singleton(this); - private final Future successfulVoidFuture = DefaultPromise.newSuccessfulPromise(this, null); + private final Future successfulVoidFuture = DefaultPromise.newSuccessfulPromise(this, null).asFuture(); @Override public EventExecutor next() { @@ -87,12 +87,13 @@ public abstract class AbstractEventExecutor extends AbstractExecutorService impl Future f = (Future) successfulVoidFuture; return f; } - return DefaultPromise.newSuccessfulPromise(this, result); + return DefaultPromise.newSuccessfulPromise(this, result).asFuture(); } @Override public Future newFailedFuture(Throwable cause) { - return DefaultPromise.newFailedPromise(this, cause); + Promise promise = DefaultPromise.newFailedPromise(this, cause); + return promise.asFuture(); } @Override diff --git a/common/src/main/java/io/netty/util/concurrent/AbstractScheduledEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/AbstractScheduledEventExecutor.java index 778db2f28d..478d479cb1 100644 --- a/common/src/main/java/io/netty/util/concurrent/AbstractScheduledEventExecutor.java +++ b/common/src/main/java/io/netty/util/concurrent/AbstractScheduledEventExecutor.java @@ -393,6 +393,11 @@ public abstract class AbstractScheduledEventExecutor extends AbstractEventExecut return this; } + @Override + public boolean cancel() { + return cancel(false); + } + @Override public boolean isSuccess() { return future.isSuccess(); diff --git a/common/src/main/java/io/netty/util/concurrent/AsynchronousResult.java b/common/src/main/java/io/netty/util/concurrent/AsynchronousResult.java new file mode 100644 index 0000000000..968585aa91 --- /dev/null +++ b/common/src/main/java/io/netty/util/concurrent/AsynchronousResult.java @@ -0,0 +1,96 @@ +/* + * Copyright 2021 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.util.concurrent; + +import java.util.concurrent.CancellationException; + +/** + * A result of an asynchronous operation. + *

+ * This interface is used as the super-interface of {@link Promise} and {@link Future}, and these should generally be + * used instead. + */ +interface AsynchronousResult { + /** + * Cancel this asynchronous operation, unless it has already been completed. + *

+ * A cancelled operation is considered to be {@linkplain #isFailed() failed}. + *

+ * If the cancellation was successful, the result of this operation will be that it has failed with a + * {@link CancellationException}. + *

+ * Cancellation will not cause any threads working on the operation to be {@linkplain Thread#interrupt() + * interrupted}. + * + * @return {@code true} if the operation was cancelled by this call, otherwise {@code false}. + */ + boolean cancel(); + + /** + * Returns {@code true} if and only if the operation was completed successfully. + */ + boolean isSuccess(); + + /** + * Returns {@code true} if and only if the operation was completed and failed. + */ + boolean isFailed(); + + /** + * Return {@code true} if this operation has been {@linkplain #cancel() cancelled}. + * + * @return {@code true} if this operation has been cancelled, otherwise {@code false}. + */ + boolean isCancelled(); + + /** + * Return {@code true} if this operation has been completed either {@linkplain Promise#setSuccess(Object) + * successfully}, {@linkplain Promise#setFailure(Throwable) unsuccessfully}, or through + * {@linkplain #cancel() cancellation}. + * + * @return {@code true} if this operation has completed, otherwise {@code false}. + */ + boolean isDone(); + + /** + * returns {@code true} if and only if the operation can be cancelled via {@link #cancel()}. + */ + boolean isCancellable(); + + /** + * Return the successful result of this asynchronous operation, if any. + * If the operation has not yet been completed, then this will throw {@link IllegalStateException}. + * If the operation has been cancelled or failed with an exception, then this returns {@code null}. + * Note that asynchronous operations can also be completed successfully with a {@code null} result. + * + * @return the result of this operation, if completed successfully. + * @throws IllegalStateException if this {@code Future} or {@link Promise} has not completed yet. + */ + V getNow(); + + /** + * Returns the cause of the failed operation if the operation has failed. + * + * @return The cause of the failure, if any. Otherwise {@code null} if succeeded. + * @throws IllegalStateException if this {@code Promise} has not completed yet. + */ + Throwable cause(); + + /** + * Returns the {@link EventExecutor} that is tied to this {@link Promise} or {@link Future}. + */ + EventExecutor executor(); +} diff --git a/common/src/main/java/io/netty/util/concurrent/DefaultFutureCompletionStage.java b/common/src/main/java/io/netty/util/concurrent/DefaultFutureCompletionStage.java index 9043b36c83..62b2b013ce 100644 --- a/common/src/main/java/io/netty/util/concurrent/DefaultFutureCompletionStage.java +++ b/common/src/main/java/io/netty/util/concurrent/DefaultFutureCompletionStage.java @@ -201,7 +201,7 @@ final class DefaultFutureCompletionStage implements FutureCompletionStage promise.setFailure(cause); } }); - return promise.asStage(); + return promise.asFuture().asStage(); } private static void thenApplyAsync0(Promise promise, V value, Function fn) { @@ -234,7 +234,7 @@ final class DefaultFutureCompletionStage implements FutureCompletionStage promise.setFailure(cause); } }); - return promise.asStage(); + return promise.asFuture().asStage(); } private static void thenAcceptAsync0(Promise promise, V value, Consumer action) { @@ -299,7 +299,7 @@ final class DefaultFutureCompletionStage implements FutureCompletionStage applyAndNotify(promise, value2, value1, fn); } }, otherExecutor(executor)); - return promise.asStage(); + return promise.asFuture().asStage(); } private Executor otherExecutor(Executor executor) { @@ -342,7 +342,7 @@ final class DefaultFutureCompletionStage implements FutureCompletionStage }; whenCompleteAsync(consumer, executor); other.whenCompleteAsync(consumer, otherExecutor(executor)); - return promise.asStage(); + return promise.asFuture().asStage(); } @Override @@ -363,7 +363,7 @@ final class DefaultFutureCompletionStage implements FutureCompletionStage }; whenCompleteAsync(consumer, executor); other.whenCompleteAsync(consumer, otherExecutor(executor)); - return promise.asStage(); + return promise.asFuture().asStage(); } @Override @@ -384,7 +384,7 @@ final class DefaultFutureCompletionStage implements FutureCompletionStage }; whenCompleteAsync(consumer, executor); other.whenCompleteAsync(consumer, otherExecutor(executor)); - return promise.asStage(); + return promise.asFuture().asStage(); } @Override @@ -407,7 +407,7 @@ final class DefaultFutureCompletionStage implements FutureCompletionStage promise.setFailure(cause); } }); - return promise.asStage(); + return promise.asFuture().asStage(); } private static void thenComposeAsync0( @@ -449,7 +449,7 @@ final class DefaultFutureCompletionStage implements FutureCompletionStage promise.setSuccess(result); } }); - return promise.asStage(); + return promise.asFuture().asStage(); } @Override @@ -466,7 +466,7 @@ final class DefaultFutureCompletionStage implements FutureCompletionStage safeExecute(executor, () -> whenCompleteAsync0(promise, f, action), promise); } }); - return promise.asStage(); + return promise.asFuture().asStage(); } private static void whenCompleteAsync0( @@ -501,7 +501,7 @@ final class DefaultFutureCompletionStage implements FutureCompletionStage safeExecute(executor, () -> handleAsync0(promise, f, fn), promise); } }); - return promise.asStage(); + return promise.asFuture().asStage(); } @SuppressWarnings("unchecked") 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 2203929756..c72417c0d0 100644 --- a/common/src/main/java/io/netty/util/concurrent/DefaultPromise.java +++ b/common/src/main/java/io/netty/util/concurrent/DefaultPromise.java @@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.MILLISECONDS; -public class DefaultPromise implements Promise { +public class DefaultPromise implements Promise, Future { private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultPromise.class); private static final InternalLogger rejectedExecutionLogger = InternalLoggerFactory.getInstance(DefaultPromise.class.getName() + ".rejectedExecution"); @@ -157,6 +157,11 @@ public class DefaultPromise implements Promise { return !isDone0(result) || !isCancelled0(result); } + @Override + public Future asFuture() { + return this; + } + @Override public boolean isSuccess() { Object result = this.result; @@ -212,7 +217,7 @@ public class DefaultPromise implements Promise { } @Override - public Promise addListener(FutureListener listener) { + public Future addListener(FutureListener listener) { requireNonNull(listener, "listener"); addListener0(listener, null); @@ -224,7 +229,7 @@ public class DefaultPromise implements Promise { } @Override - public Promise addListener(C context, FutureContextListener listener) { + public Future addListener(C context, FutureContextListener listener) { requireNonNull(listener, "listener"); addListener0(listener, context == null ? NULL_CONTEXT : context); @@ -377,6 +382,11 @@ public class DefaultPromise implements Promise { throw new ExecutionException(cause); } + @Override + public boolean cancel() { + return cancel(false); + } + /** * @param mayInterruptIfRunning this value has no effect in this implementation. */ diff --git a/common/src/main/java/io/netty/util/concurrent/Future.java b/common/src/main/java/io/netty/util/concurrent/Future.java index 7f6a8ca730..7f946fbc7e 100644 --- a/common/src/main/java/io/netty/util/concurrent/Future.java +++ b/common/src/main/java/io/netty/util/concurrent/Future.java @@ -151,30 +151,7 @@ import java.util.function.Function; * */ @SuppressWarnings("ClassNameSameAsAncestorName") -public interface Future extends java.util.concurrent.Future { - /** - * Returns {@code true} if and only if the operation was completed successfully. - */ - boolean isSuccess(); - - /** - * Returns {@code true} if and only if the operation was completed and failed. - */ - boolean isFailed(); - - /** - * returns {@code true} if and only if the operation can be cancelled via {@link #cancel(boolean)}. - */ - boolean isCancellable(); - - /** - * Returns the cause of the failed I/O operation if the I/O operation has failed. - * - * @return the cause of the failure. {@code null} if succeeded. - * @throws IllegalStateException if this {@code Future} has not completed yet. - */ - Throwable cause(); - +public interface Future extends java.util.concurrent.Future, AsynchronousResult { /** * Adds the specified listener to this future. The specified listener is notified when this future is {@linkplain * #isDone() done}. If this future is already completed, the specified listener is notified immediately. @@ -258,14 +235,6 @@ public interface Future extends java.util.concurrent.Future { */ boolean awaitUninterruptibly(long timeoutMillis); - /** - * Return the result without blocking. If the future is not done yet this will throw {@link IllegalStateException}. - *

- * - * @throws IllegalStateException if this {@code Future} has not completed yet. - */ - V getNow(); - /** * {@inheritDoc} *

@@ -274,11 +243,6 @@ public interface Future extends java.util.concurrent.Future { @Override boolean cancel(boolean mayInterruptIfRunning); - /** - * Returns the {@link EventExecutor} that is tied to this {@link Future}. - */ - EventExecutor executor(); - @Override default V get() throws InterruptedException, ExecutionException { await(); diff --git a/common/src/main/java/io/netty/util/concurrent/FutureCompletionStage.java b/common/src/main/java/io/netty/util/concurrent/FutureCompletionStage.java index 1bb3a544c2..8301f96361 100644 --- a/common/src/main/java/io/netty/util/concurrent/FutureCompletionStage.java +++ b/common/src/main/java/io/netty/util/concurrent/FutureCompletionStage.java @@ -28,7 +28,7 @@ import java.util.function.Function; /** * A {@link CompletionStage} that provides the same threading semantics and guarantees as the underlying - * {@link io.netty.util.concurrent.Future}, which means that all the callbacks will be executed by {@link #executor()} + * {@link Future}, which means that all the callbacks will be executed by {@link #executor()} * if not specified otherwise (by calling the corresponding *Async methods). * * Please be aware that {@link FutureCompletionStage#toCompletableFuture()} is not supported and so will throw @@ -188,7 +188,7 @@ public interface FutureCompletionStage extends CompletionStage { static FutureCompletionStage toFutureCompletionStage(CompletionStage stage, EventExecutor executor) { Objects.requireNonNull(stage, "stage"); Objects.requireNonNull(executor, "executor"); - if (stage instanceof FutureCompletionStage && ((FutureCompletionStage) stage).executor() == executor) { + if (stage instanceof FutureCompletionStage && ((FutureCompletionStage) stage).executor() == executor) { return (FutureCompletionStage) stage; } @@ -208,6 +208,6 @@ public interface FutureCompletionStage extends CompletionStage { promise.setSuccess(v); } }); - return promise.asStage(); + return promise.asFuture().asStage(); } } diff --git a/common/src/main/java/io/netty/util/concurrent/Futures.java b/common/src/main/java/io/netty/util/concurrent/Futures.java index 609916c619..f9eeb001c2 100644 --- a/common/src/main/java/io/netty/util/concurrent/Futures.java +++ b/common/src/main/java/io/netty/util/concurrent/Futures.java @@ -63,8 +63,9 @@ final class Futures { } Promise promise = future.executor().newPromise(); future.addListener(new Mapper<>(promise, mapper)); - promise.addListener(future, propagateCancel()); - return promise; + Future mappedFuture = promise.asFuture(); + mappedFuture.addListener(future, propagateCancel()); + return mappedFuture; } /** @@ -98,12 +99,13 @@ final class Futures { requireNonNull(mapper, "mapper"); Promise promise = future.executor().newPromise(); future.addListener(new FlatMapper<>(promise, mapper)); + Future mappedFuture = promise.asFuture(); if (!future.isSuccess()) { // Propagate cancellation if future is either incomplete or failed. // Failed means it could be cancelled, so that needs to be propagated. - promise.addListener(future, propagateCancel()); + mappedFuture.addListener(future, propagateCancel()); } - return promise; + return mappedFuture; } @SuppressWarnings("unchecked") @@ -120,7 +122,7 @@ final class Futures { if (completed.isCancelled()) { // Don't check or log if cancellation propagation fails. // Propagation goes both ways, which means at least one future will already be cancelled here. - recipient.cancel(false); + recipient.cancel(); } else { Throwable cause = completed.cause(); recipient.tryFailure(cause); @@ -219,7 +221,7 @@ final class Futures { propagateUncommonCompletion(future, recipient); } else { future.addListener(recipient, passThrough()); - recipient.addListener(future, propagateCancel()); + recipient.asFuture().addListener(future, propagateCancel()); } } catch (Throwable e) { tryFailure(recipient, e, logger); @@ -246,7 +248,7 @@ final class Futures { if (!future.isSuccess()) { // Propagate cancellation if future is either incomplete or failed. // Failed means it could be cancelled, so that needs to be propagated. - promise.addListener(future, propagateCancel()); + promise.asFuture().addListener(future, propagateCancel()); } future.addListener(promise, passThrough()); } diff --git a/common/src/main/java/io/netty/util/concurrent/GlobalEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/GlobalEventExecutor.java index 563e5f6798..bc1bd54e78 100644 --- a/common/src/main/java/io/netty/util/concurrent/GlobalEventExecutor.java +++ b/common/src/main/java/io/netty/util/concurrent/GlobalEventExecutor.java @@ -68,7 +68,7 @@ public final class GlobalEventExecutor extends AbstractScheduledEventExecutor im volatile Thread thread; private final Future terminationFuture = DefaultPromise.newFailedPromise( - this, new UnsupportedOperationException()); + this, new UnsupportedOperationException()).asFuture(); private GlobalEventExecutor() { threadFactory = ThreadExecutorMap.apply(new DefaultThreadFactory( diff --git a/common/src/main/java/io/netty/util/concurrent/ImmediateEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/ImmediateEventExecutor.java index 9076641f28..d2c945320f 100644 --- a/common/src/main/java/io/netty/util/concurrent/ImmediateEventExecutor.java +++ b/common/src/main/java/io/netty/util/concurrent/ImmediateEventExecutor.java @@ -55,7 +55,7 @@ public final class ImmediateEventExecutor extends AbstractEventExecutor { }; private final Future terminationFuture = DefaultPromise.newFailedPromise( - GlobalEventExecutor.INSTANCE, new UnsupportedOperationException()); + GlobalEventExecutor.INSTANCE, new UnsupportedOperationException()).asFuture(); private ImmediateEventExecutor() { } diff --git a/common/src/main/java/io/netty/util/concurrent/MultithreadEventExecutorGroup.java b/common/src/main/java/io/netty/util/concurrent/MultithreadEventExecutorGroup.java index 338a6af9c4..4442740355 100644 --- a/common/src/main/java/io/netty/util/concurrent/MultithreadEventExecutorGroup.java +++ b/common/src/main/java/io/netty/util/concurrent/MultithreadEventExecutorGroup.java @@ -232,7 +232,7 @@ public class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup { @Override public final Future terminationFuture() { - return terminationFuture; + return terminationFuture.asFuture(); } @Override diff --git a/common/src/main/java/io/netty/util/concurrent/Promise.java b/common/src/main/java/io/netty/util/concurrent/Promise.java index 4d963b32a6..3ca0fc4572 100644 --- a/common/src/main/java/io/netty/util/concurrent/Promise.java +++ b/common/src/main/java/io/netty/util/concurrent/Promise.java @@ -15,14 +15,12 @@ */ package io.netty.util.concurrent; -import java.util.concurrent.CancellationException; - /** * Special {@link Future} which is writable. */ -public interface Promise extends Future { +public interface Promise extends AsynchronousResult { /** - * Marks this future as a success and notifies all listeners. + * Marks this promise as a success and notifies all listeners attached to the {@linkplain #asFuture() future}. *

* If it is success or failed already it will throw an {@link IllegalStateException}. */ @@ -31,37 +29,39 @@ public interface Promise extends Future { /** * Marks this future as a success and notifies all listeners. * - * @return {@code true} if and only if successfully marked this future as a success. Otherwise {@code false} because - * this future is already marked as either a success or a failure. + * @return {@code true} if and only if successfully marked this promise as a success. + * Otherwise {@code false} because this promise is already marked as either a success or a failure. */ boolean trySuccess(V result); /** - * Marks this future as a failure and notifies all listeners. + * Marks this promise as a failure and notifies all listeners attached to the {@linkplain #asFuture() future}. *

* If it is success or failed already it will throw an {@link IllegalStateException}. */ Promise setFailure(Throwable cause); /** - * Marks this future as a failure and notifies all listeners. + * Marks this promise as a failure and notifies all listeners. * - * @return {@code true} if and only if successfully marked this future as a failure. Otherwise {@code false} because - * this future is already marked as either a success or a failure. + * @return {@code true} if and only if successfully marked this promise as a failure. + * Otherwise {@code false} because this promise is already marked as either a success or a failure. */ boolean tryFailure(Throwable cause); /** - * Make this future impossible to cancel. + * Make this promise impossible to cancel. * - * @return {@code true} if and only if successfully marked this future as uncancellable, or it is already done - * without being cancelled. Otherwise {@code false} if this future has been cancelled already. + * @return {@code true} if and only if successfully marked this promise as uncancellable, or it is already done + * without being cancelled. Otherwise {@code false} if this promise has been cancelled already. */ boolean setUncancellable(); - @Override - Promise addListener(FutureListener listener); - - @Override - Promise addListener(C context, FutureContextListener listener); + /** + * Return the {@link Future} instance is associated with this promise. + * This future will be completed upon completion of this promise. + * + * @return A future instance associated with this promise. + */ + Future asFuture(); } diff --git a/common/src/main/java/io/netty/util/concurrent/RunnableFutureAdapter.java b/common/src/main/java/io/netty/util/concurrent/RunnableFutureAdapter.java index 3ac1c4bc68..9ba77d8c07 100644 --- a/common/src/main/java/io/netty/util/concurrent/RunnableFutureAdapter.java +++ b/common/src/main/java/io/netty/util/concurrent/RunnableFutureAdapter.java @@ -27,11 +27,13 @@ import java.util.concurrent.TimeoutException; final class RunnableFutureAdapter implements RunnableFuture { private final Promise promise; + private final Future future; private final Callable task; RunnableFutureAdapter(Promise promise, Callable task) { this.promise = requireNonNull(promise, "promise"); this.task = requireNonNull(task, "task"); + future = promise.asFuture(); } @Override @@ -61,58 +63,58 @@ final class RunnableFutureAdapter implements RunnableFuture { @Override public RunnableFuture addListener(FutureListener listener) { - promise.addListener(listener); + future.addListener(listener); return this; } @Override public RunnableFuture addListener(C context, FutureContextListener listener) { - promise.addListener(context, listener); + future.addListener(context, listener); return this; } @Override public RunnableFuture sync() throws InterruptedException { - promise.sync(); + future.sync(); return this; } @Override public RunnableFuture syncUninterruptibly() { - promise.syncUninterruptibly(); + future.syncUninterruptibly(); return this; } @Override public RunnableFuture await() throws InterruptedException { - promise.await(); + future.await(); return this; } @Override public RunnableFuture awaitUninterruptibly() { - promise.awaitUninterruptibly(); + future.awaitUninterruptibly(); return this; } @Override public boolean await(long timeout, TimeUnit unit) throws InterruptedException { - return promise.await(timeout, unit); + return future.await(timeout, unit); } @Override public boolean await(long timeoutMillis) throws InterruptedException { - return promise.await(timeoutMillis); + return future.await(timeoutMillis); } @Override public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { - return promise.awaitUninterruptibly(timeout, unit); + return future.awaitUninterruptibly(timeout, unit); } @Override public boolean awaitUninterruptibly(long timeoutMillis) { - return promise.awaitUninterruptibly(timeoutMillis); + return future.awaitUninterruptibly(timeoutMillis); } @Override @@ -134,7 +136,12 @@ final class RunnableFutureAdapter implements RunnableFuture { @Override public boolean cancel(boolean mayInterruptIfRunning) { - return promise.cancel(mayInterruptIfRunning); + return future.cancel(mayInterruptIfRunning); + } + + @Override + public boolean cancel() { + return cancel(false); } @Override @@ -149,12 +156,12 @@ final class RunnableFutureAdapter implements RunnableFuture { @Override public V get() throws InterruptedException, ExecutionException { - return promise.get(); + return future.get(); } @Override public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - return promise.get(timeout, unit); + return future.get(timeout, unit); } @Override diff --git a/common/src/main/java/io/netty/util/concurrent/RunnableScheduledFutureAdapter.java b/common/src/main/java/io/netty/util/concurrent/RunnableScheduledFutureAdapter.java index 0a53a3f373..5129ef5a38 100644 --- a/common/src/main/java/io/netty/util/concurrent/RunnableScheduledFutureAdapter.java +++ b/common/src/main/java/io/netty/util/concurrent/RunnableScheduledFutureAdapter.java @@ -41,12 +41,14 @@ final class RunnableScheduledFutureAdapter implements AbstractScheduledEventE private final AbstractScheduledEventExecutor executor; private final Promise promise; + private final Future future; private final Callable callable; RunnableScheduledFutureAdapter(AbstractScheduledEventExecutor executor, Promise promise, Callable callable, long deadlineNanos, long periodNanos) { this.executor = requireNonNull(executor, "executor"); this.promise = requireNonNull(promise, "promise"); + future = promise.asFuture(); this.callable = requireNonNull(callable, "callable"); this.deadlineNanos = deadlineNanos; this.periodNanos = periodNanos; @@ -133,13 +135,18 @@ final class RunnableScheduledFutureAdapter implements AbstractScheduledEventE */ @Override public boolean cancel(boolean mayInterruptIfRunning) { - boolean canceled = promise.cancel(mayInterruptIfRunning); + boolean canceled = future.cancel(mayInterruptIfRunning); if (canceled) { executor.removeScheduled(this); } return canceled; } + @Override + public boolean cancel() { + return cancel(false); + } + @Override public boolean isSuccess() { return promise.isSuccess(); @@ -162,58 +169,58 @@ final class RunnableScheduledFutureAdapter implements AbstractScheduledEventE @Override public RunnableScheduledFuture addListener(FutureListener listener) { - promise.addListener(listener); + future.addListener(listener); return this; } @Override public RunnableScheduledFuture addListener(C context, FutureContextListener listener) { - promise.addListener(context, listener); + future.addListener(context, listener); return this; } @Override public RunnableScheduledFuture sync() throws InterruptedException { - promise.sync(); + future.sync(); return this; } @Override public RunnableScheduledFuture syncUninterruptibly() { - promise.syncUninterruptibly(); + future.syncUninterruptibly(); return this; } @Override public RunnableScheduledFuture await() throws InterruptedException { - promise.await(); + future.await(); return this; } @Override public RunnableScheduledFuture awaitUninterruptibly() { - promise.awaitUninterruptibly(); + future.awaitUninterruptibly(); return this; } @Override public boolean await(long timeout, TimeUnit unit) throws InterruptedException { - return promise.await(timeout, unit); + return future.await(timeout, unit); } @Override public boolean await(long timeoutMillis) throws InterruptedException { - return promise.await(timeoutMillis); + return future.await(timeoutMillis); } @Override public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { - return promise.awaitUninterruptibly(timeout, unit); + return future.awaitUninterruptibly(timeout, unit); } @Override public boolean awaitUninterruptibly(long timeoutMillis) { - return promise.awaitUninterruptibly(timeoutMillis); + return future.awaitUninterruptibly(timeoutMillis); } @Override @@ -228,7 +235,7 @@ final class RunnableScheduledFutureAdapter implements AbstractScheduledEventE @Override public boolean isCancelled() { - return promise.isCancelled(); + return future.isCancelled(); } @Override @@ -238,12 +245,12 @@ final class RunnableScheduledFutureAdapter implements AbstractScheduledEventE @Override public V get() throws InterruptedException, ExecutionException { - return promise.get(); + return future.get(); } @Override public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - return promise.get(timeout, unit); + return future.get(timeout, unit); } @Override diff --git a/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java index 11bc8d5f1d..3bd3515088 100644 --- a/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java +++ b/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java @@ -546,7 +546,7 @@ public class SingleThreadEventExecutor extends AbstractScheduledEventExecutor im gracefulShutdownTimeout = unit.toNanos(timeout); if (ensureThreadStarted(oldState)) { - return terminationFuture; + return terminationFuture.asFuture(); } if (wakeup) { @@ -561,7 +561,7 @@ public class SingleThreadEventExecutor extends AbstractScheduledEventExecutor im @Override public final Future terminationFuture() { - return terminationFuture; + return terminationFuture.asFuture(); } @Override diff --git a/common/src/main/java/io/netty/util/concurrent/UnaryPromiseNotifier.java b/common/src/main/java/io/netty/util/concurrent/UnaryPromiseNotifier.java index 68faaf33eb..9b5e12d66f 100644 --- a/common/src/main/java/io/netty/util/concurrent/UnaryPromiseNotifier.java +++ b/common/src/main/java/io/netty/util/concurrent/UnaryPromiseNotifier.java @@ -39,7 +39,7 @@ public final class UnaryPromiseNotifier implements FutureListener { logger.warn("Failed to mark a promise as success because it is done already: {}", promise); } } else if (completedFuture.isCancelled()) { - if (!promise.cancel(false)) { + if (!promise.cancel()) { logger.warn("Failed to cancel a promise because it is done already: {}", promise); } } else { diff --git a/common/src/main/java/io/netty/util/concurrent/UnorderedThreadPoolEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/UnorderedThreadPoolEventExecutor.java index b52d4d65f6..7ac16638de 100644 --- a/common/src/main/java/io/netty/util/concurrent/UnorderedThreadPoolEventExecutor.java +++ b/common/src/main/java/io/netty/util/concurrent/UnorderedThreadPoolEventExecutor.java @@ -99,12 +99,13 @@ public final class UnorderedThreadPoolEventExecutor extends ScheduledThreadPoolE @Override public Future newSucceededFuture(V result) { - return DefaultPromise.newSuccessfulPromise(this, result); + return DefaultPromise.newSuccessfulPromise(this, result).asFuture(); } @Override public Future newFailedFuture(Throwable cause) { - return DefaultPromise.newFailedPromise(this, cause); + Promise promise = DefaultPromise.newFailedPromise(this, cause); + return promise.asFuture(); } @Override @@ -140,7 +141,7 @@ public final class UnorderedThreadPoolEventExecutor extends ScheduledThreadPoolE @Override public Future terminationFuture() { - return terminationFuture; + return terminationFuture.asFuture(); } @Override diff --git a/common/src/main/java/io/netty/util/internal/PromiseNotificationUtil.java b/common/src/main/java/io/netty/util/internal/PromiseNotificationUtil.java index 401eebcaaa..a216f0b855 100644 --- a/common/src/main/java/io/netty/util/internal/PromiseNotificationUtil.java +++ b/common/src/main/java/io/netty/util/internal/PromiseNotificationUtil.java @@ -29,7 +29,7 @@ public final class PromiseNotificationUtil { * Try to cancel the {@link Promise} and log if {@code logger} is not {@code null} in case this fails. */ public static void tryCancel(Promise p, InternalLogger logger) { - if (!p.cancel(false) && logger != null) { + if (!p.cancel() && logger != null) { Throwable err = p.cause(); if (err == null) { logger.warn("Failed to cancel promise because it has succeeded already: {}", p); diff --git a/common/src/test/java/io/netty/util/concurrent/DefaultFutureCompletionStageTest.java b/common/src/test/java/io/netty/util/concurrent/DefaultFutureCompletionStageTest.java index 99dacdcff6..d92b70f5ea 100644 --- a/common/src/test/java/io/netty/util/concurrent/DefaultFutureCompletionStageTest.java +++ b/common/src/test/java/io/netty/util/concurrent/DefaultFutureCompletionStageTest.java @@ -79,7 +79,7 @@ public class DefaultFutureCompletionStageTest { public void testSameExecutorAndFuture() { EventExecutor executor = executor(); Promise promise = executor.newPromise(); - FutureCompletionStage stage = new DefaultFutureCompletionStage<>(promise); + FutureCompletionStage stage = new DefaultFutureCompletionStage<>(promise.asFuture()); assertSame(executor, stage.executor()); assertSame(promise, stage.future()); } @@ -88,7 +88,7 @@ public class DefaultFutureCompletionStageTest { public void testThrowsUnsupportedOperationException() { EventExecutor executor = executor(); Promise promise = executor.newPromise(); - FutureCompletionStage stage = new DefaultFutureCompletionStage<>(promise); + FutureCompletionStage stage = new DefaultFutureCompletionStage<>(promise.asFuture()); assertThrows(UnsupportedOperationException.class, () -> stage.toCompletableFuture()); } @@ -766,7 +766,7 @@ public class DefaultFutureCompletionStageTest { // may use different threads. for (int i = 0; i < 1000; i++) { Promise promise = executor.newPromise(); - FutureCompletionStage stage = new DefaultFutureCompletionStage<>(promise); + FutureCompletionStage stage = new DefaultFutureCompletionStage<>(promise.asFuture()); CompletableFuture completableFuture = new CompletableFuture<>(); Future f = fn.apply(stage, completableFuture).future(); diff --git a/common/src/test/java/io/netty/util/concurrent/FuturesTest.java b/common/src/test/java/io/netty/util/concurrent/FuturesTest.java index 0cdceea76b..862e52f213 100644 --- a/common/src/test/java/io/netty/util/concurrent/FuturesTest.java +++ b/common/src/test/java/io/netty/util/concurrent/FuturesTest.java @@ -20,7 +20,6 @@ import org.junit.jupiter.api.Test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; -import static io.netty.util.concurrent.DefaultPromise.newSuccessfulPromise; import static io.netty.util.concurrent.ImmediateEventExecutor.INSTANCE; import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; @@ -39,7 +38,7 @@ class FuturesTest { } @Test - public void mapMustApplyMapperFunctionOnSuccededFuture() { + public void mapMustApplyMapperFunctionOnSucceededFuture() { DefaultPromise promise = new DefaultPromise<>(INSTANCE); promise.setSuccess(42); assertThat(promise.map(i -> i.toString()).getNow()).isEqualTo("42"); @@ -108,16 +107,16 @@ class FuturesTest { @Test public void flatMapMustApplyMapperFunctionWhenFutureSucceeds() { DefaultPromise promise = new DefaultPromise<>(INSTANCE); - Future strFut = promise.flatMap(i -> newSuccessfulPromise(INSTANCE, i.toString())); + Future strFut = promise.flatMap(i -> INSTANCE.newSucceededFuture(i.toString())); promise.setSuccess(42); assertThat(strFut.getNow()).isEqualTo("42"); } @Test - public void flatMapMustApplyMapperFunctionOnSuccededFuture() { + public void flatMapMustApplyMapperFunctionOnSucceededFuture() { DefaultPromise promise = new DefaultPromise<>(INSTANCE); promise.setSuccess(42); - assertThat(promise.flatMap(i -> newSuccessfulPromise(INSTANCE, i.toString())).getNow()).isEqualTo("42"); + assertThat(promise.flatMap(i -> INSTANCE.newSucceededFuture(i.toString())).getNow()).isEqualTo("42"); } @Test @@ -125,7 +124,7 @@ class FuturesTest { DefaultPromise promise = new DefaultPromise<>(INSTANCE); Exception cause = new Exception("boom"); promise.setFailure(cause); - assertThat(promise.flatMap(i -> newSuccessfulPromise(INSTANCE, i.toString())).cause()).isSameAs(cause); + assertThat(promise.flatMap(i -> INSTANCE.newSucceededFuture(i.toString())).cause()).isSameAs(cause); } @Test @@ -136,7 +135,7 @@ class FuturesTest { AtomicInteger counter = new AtomicInteger(); assertThat(promise.flatMap(i -> { counter.getAndIncrement(); - return newSuccessfulPromise(INSTANCE, i.toString()); + return INSTANCE.newSucceededFuture(i.toString()); }).cause()).isSameAs(cause); assertThat(counter.get()).isZero(); } @@ -165,7 +164,7 @@ class FuturesTest { @Test public void cancelOnFutureFromFlatMapMustCancelOriginalFuture() { DefaultPromise promise = new DefaultPromise<>(INSTANCE); - Future strFut = promise.flatMap(i -> newSuccessfulPromise(INSTANCE, i.toString())); + Future strFut = promise.flatMap(i -> INSTANCE.newSucceededFuture(i.toString())); strFut.cancel(false); assertTrue(promise.isCancelled()); assertTrue(strFut.isCancelled()); @@ -174,7 +173,7 @@ class FuturesTest { @Test public void cancelOnOriginalFutureMustCancelFutureFromFlatMap() { DefaultPromise promise = new DefaultPromise<>(INSTANCE); - Future strFut = promise.flatMap(i -> newSuccessfulPromise(INSTANCE, i.toString())); + Future strFut = promise.flatMap(i -> INSTANCE.newSucceededFuture(i.toString())); promise.cancel(false); assertTrue(promise.isCancelled()); assertTrue(strFut.isCancelled()); diff --git a/common/src/test/java/io/netty/util/concurrent/PromiseCombinerTest.java b/common/src/test/java/io/netty/util/concurrent/PromiseCombinerTest.java index 7d80a7fc4e..52a701fb5b 100644 --- a/common/src/test/java/io/netty/util/concurrent/PromiseCombinerTest.java +++ b/common/src/test/java/io/netty/util/concurrent/PromiseCombinerTest.java @@ -17,46 +17,30 @@ package io.netty.util.concurrent; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import static io.netty.util.concurrent.ImmediateEventExecutor.INSTANCE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; public class PromiseCombinerTest { - @Mock private Promise p1; - private FutureListener l1; - private final FutureListenerConsumer l1Consumer = new FutureListenerConsumer() { - @Override - public void accept(FutureListener listener) { - l1 = listener; - } - }; - @Mock + private Future f1; private Promise p2; - private FutureListener l2; - private final FutureListenerConsumer l2Consumer = new FutureListenerConsumer() { - @Override - public void accept(FutureListener listener) { - l2 = listener; - } - }; - @Mock + private Future f2; private Promise p3; private PromiseCombiner combiner; @BeforeEach public void setup() { - MockitoAnnotations.initMocks(this); - combiner = new PromiseCombiner(ImmediateEventExecutor.INSTANCE); + p1 = INSTANCE.newPromise(); + p2 = INSTANCE.newPromise(); + p3 = INSTANCE.newPromise(); + f1 = p1.asFuture(); + f2 = p2.asFuture(); + combiner = new PromiseCombiner(INSTANCE); } @Test @@ -68,13 +52,15 @@ public class PromiseCombinerTest { // expected } combiner.finish(p1); - verify(p1).trySuccess(null); + assertTrue(p1.isSuccess()); + assertThat(p1.getNow()).isNull(); } @Test public void testNullAggregatePromise() { combiner.finish(p1); - verify(p1).trySuccess(null); + assertTrue(p1.isSuccess()); + assertThat(p1.getNow()).isNull(); } @Test @@ -90,13 +76,13 @@ public class PromiseCombinerTest { @Test public void testAddAfterFinish() { combiner.finish(p1); - assertThrows(IllegalStateException.class, () -> combiner.add(p2)); + assertThrows(IllegalStateException.class, () -> combiner.add(f2)); } @Test public void testAddAllAfterFinish() { combiner.finish(p1); - assertThrows(IllegalStateException.class, () -> combiner.addAll(p2)); + assertThrows(IllegalStateException.class, () -> combiner.addAll(f2)); } @Test @@ -107,65 +93,59 @@ public class PromiseCombinerTest { @Test public void testAddAllSuccess() throws Exception { - mockSuccessPromise(p1, l1Consumer); - mockSuccessPromise(p2, l2Consumer); - combiner.addAll(p1, p2); + p1.setSuccess(null); + combiner.addAll(f1, f2); combiner.finish(p3); - l1.operationComplete(p1); - verifyNotCompleted(p3); - l2.operationComplete(p2); - verifySuccess(p3); + assertFalse(p3.isDone()); + p2.setSuccess(null); + assertTrue(p3.isDone()); + assertTrue(p3.isSuccess()); } @Test public void testAddSuccess() throws Exception { - mockSuccessPromise(p1, l1Consumer); - mockSuccessPromise(p2, l2Consumer); - combiner.add(p1); - l1.operationComplete(p1); - combiner.add(p2); - l2.operationComplete(p2); - verifyNotCompleted(p3); + p1.setSuccess(null); + p2.setSuccess(null); + combiner.add(f1); + combiner.add(f2); + assertFalse(p3.isDone()); combiner.finish(p3); - verifySuccess(p3); + assertTrue(p3.isSuccess()); } @Test public void testAddAllFail() throws Exception { RuntimeException e1 = new RuntimeException("fake exception 1"); RuntimeException e2 = new RuntimeException("fake exception 2"); - mockFailedPromise(p1, e1, l1Consumer); - mockFailedPromise(p2, e2, l2Consumer); - combiner.addAll(p1, p2); + combiner.addAll(f1, f2); combiner.finish(p3); - l1.operationComplete(p1); - verifyNotCompleted(p3); - l2.operationComplete(p2); - verifyFail(p3, e1); + p1.setFailure(e1); + assertFalse(p3.isDone()); + p2.setFailure(e2); + assertTrue(p3.isFailed()); + assertThat(p3.cause()).isSameAs(e1); } @Test public void testAddFail() throws Exception { RuntimeException e1 = new RuntimeException("fake exception 1"); RuntimeException e2 = new RuntimeException("fake exception 2"); - mockFailedPromise(p1, e1, l1Consumer); - mockFailedPromise(p2, e2, l2Consumer); - combiner.add(p1); - l1.operationComplete(p1); - combiner.add(p2); - l2.operationComplete(p2); - verifyNotCompleted(p3); + combiner.add(f1); + p1.setFailure(e1); + combiner.add(f2); + p2.setFailure(e2); + assertFalse(p3.isDone()); combiner.finish(p3); - verifyFail(p3, e1); + assertTrue(p3.isFailed()); + assertThat(p3.cause()).isSameAs(e1); } @Test public void testEventExecutor() { - EventExecutor executor = mock(EventExecutor.class); - when(executor.inEventLoop()).thenReturn(false); + EventExecutor executor = new SingleThreadEventExecutor(); combiner = new PromiseCombiner(executor); - Future future = mock(Future.class); + Future future = executor.newPromise().asFuture(); try { combiner.add(future); @@ -181,8 +161,7 @@ public class PromiseCombinerTest { // expected } - @SuppressWarnings("unchecked") - Promise promise = (Promise) mock(Promise.class); + Promise promise = executor.newPromise(); try { combiner.finish(promise); fail(); @@ -190,45 +169,4 @@ public class PromiseCombinerTest { // expected } } - - private static void verifyFail(Promise p, Throwable cause) { - verify(p).tryFailure(eq(cause)); - } - - private static void verifySuccess(Promise p) { - verify(p).trySuccess(null); - } - - private static void verifyNotCompleted(Promise p) { - verify(p, never()).trySuccess(any(Void.class)); - verify(p, never()).tryFailure(any(Throwable.class)); - verify(p, never()).setSuccess(any(Void.class)); - verify(p, never()).setFailure(any(Throwable.class)); - } - - private static void mockSuccessPromise(Promise p, FutureListenerConsumer consumer) { - when(p.isDone()).thenReturn(true); - when(p.isSuccess()).thenReturn(true); - mockListener(p, consumer); - } - - private static void mockFailedPromise(Promise p, Throwable cause, FutureListenerConsumer consumer) { - when(p.isDone()).thenReturn(true); - when(p.isSuccess()).thenReturn(false); - when(p.isFailed()).thenReturn(true); - when(p.cause()).thenReturn(cause); - mockListener(p, consumer); - } - - @SuppressWarnings("unchecked") - private static void mockListener(final Promise p, final FutureListenerConsumer consumer) { - doAnswer(invocation -> { - consumer.accept(invocation.getArgument(0)); - return p; - }).when(p).addListener(any(FutureListener.class)); - } - - interface FutureListenerConsumer { - void accept(FutureListener listener); - } } diff --git a/common/src/test/java/io/netty/util/concurrent/SingleThreadEventExecutorTest.java b/common/src/test/java/io/netty/util/concurrent/SingleThreadEventExecutorTest.java index 8eafe64d89..ddfe32587b 100644 --- a/common/src/test/java/io/netty/util/concurrent/SingleThreadEventExecutorTest.java +++ b/common/src/test/java/io/netty/util/concurrent/SingleThreadEventExecutorTest.java @@ -169,7 +169,7 @@ public class SingleThreadEventExecutorTest { promise.setFailure(cause); } }); - promise.syncUninterruptibly(); + promise.asFuture().syncUninterruptibly(); } finally { executor.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS); } diff --git a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java index 0371a8b56a..868b7062b7 100644 --- a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java +++ b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java @@ -61,7 +61,7 @@ public class WebSocketClientHandler extends SimpleChannelInboundHandler } public Future handshakeFuture() { - return handshakeFuture; + return handshakeFuture.asFuture(); } @Override diff --git a/example/src/main/java/io/netty/example/http2/helloworld/client/Http2SettingsHandler.java b/example/src/main/java/io/netty/example/http2/helloworld/client/Http2SettingsHandler.java index af409398f8..8127884446 100644 --- a/example/src/main/java/io/netty/example/http2/helloworld/client/Http2SettingsHandler.java +++ b/example/src/main/java/io/netty/example/http2/helloworld/client/Http2SettingsHandler.java @@ -45,7 +45,7 @@ public class Http2SettingsHandler extends SimpleChannelInboundHandler promise = entry.getValue().getValue(); - if (!promise.awaitUninterruptibly(timeout, unit)) { + if (!promise.asFuture().awaitUninterruptibly(timeout, unit)) { throw new IllegalStateException("Timed out waiting for response on stream id " + entry.getKey()); } if (promise.isFailed()) { diff --git a/example/src/main/java/io/netty/example/ocsp/OcspClientExample.java b/example/src/main/java/io/netty/example/ocsp/OcspClientExample.java index 85ab1a5b7b..9f7063fbc7 100644 --- a/example/src/main/java/io/netty/example/ocsp/OcspClientExample.java +++ b/example/src/main/java/io/netty/example/ocsp/OcspClientExample.java @@ -100,7 +100,7 @@ public class OcspClientExample { Channel channel = bootstrap.connect(host, 443).get(); try { - FullHttpResponse response = promise.get(); + FullHttpResponse response = promise.asFuture().get(); ReferenceCountUtil.release(response); } finally { channel.close(); diff --git a/example/src/main/java/io/netty/example/smtp/SmtpClientHandler.java b/example/src/main/java/io/netty/example/smtp/SmtpClientHandler.java index 2b1afc0b1a..8c75ab3d17 100644 --- a/example/src/main/java/io/netty/example/smtp/SmtpClientHandler.java +++ b/example/src/main/java/io/netty/example/smtp/SmtpClientHandler.java @@ -85,6 +85,6 @@ public class SmtpClientHandler extends SimpleChannelInboundHandler throw new RuntimeException("Still waiting for the past response"); } } - return promise.asStage(); + return promise.asFuture().asStage(); } } diff --git a/example/src/main/java/io/netty/example/socksproxy/SocksServerConnectHandler.java b/example/src/main/java/io/netty/example/socksproxy/SocksServerConnectHandler.java index dd694a9a45..ab2973224b 100644 --- a/example/src/main/java/io/netty/example/socksproxy/SocksServerConnectHandler.java +++ b/example/src/main/java/io/netty/example/socksproxy/SocksServerConnectHandler.java @@ -42,23 +42,23 @@ public final class SocksServerConnectHandler extends SimpleChannelInboundHandler if (message instanceof Socks4CommandRequest) { final Socks4CommandRequest request = (Socks4CommandRequest) message; Promise promise = ctx.executor().newPromise(); - promise.addListener(future -> { - final Channel outboundChannel = future.getNow(); - if (future.isSuccess()) { - Future responseFuture = ctx.channel().writeAndFlush( - new DefaultSocks4CommandResponse(Socks4CommandStatus.SUCCESS)); + promise.asFuture().addListener(future -> { + final Channel outboundChannel = future.getNow(); + if (future.isSuccess()) { + Future responseFuture = ctx.channel().writeAndFlush( + new DefaultSocks4CommandResponse(Socks4CommandStatus.SUCCESS)); - responseFuture.addListener(fut -> { - ctx.pipeline().remove(this); - outboundChannel.pipeline().addLast(new RelayHandler(ctx.channel())); - ctx.pipeline().addLast(new RelayHandler(outboundChannel)); - }); - } else { - ctx.channel().writeAndFlush( - new DefaultSocks4CommandResponse(Socks4CommandStatus.REJECTED_OR_FAILED)); - SocksServerUtils.closeOnFlush(ctx.channel()); - } + responseFuture.addListener(fut -> { + ctx.pipeline().remove(this); + outboundChannel.pipeline().addLast(new RelayHandler(ctx.channel())); + ctx.pipeline().addLast(new RelayHandler(outboundChannel)); }); + } else { + ctx.channel().writeAndFlush( + new DefaultSocks4CommandResponse(Socks4CommandStatus.REJECTED_OR_FAILED)); + SocksServerUtils.closeOnFlush(ctx.channel()); + } + }); final Channel inboundChannel = ctx.channel(); b.group(inboundChannel.executor()) @@ -81,27 +81,27 @@ public final class SocksServerConnectHandler extends SimpleChannelInboundHandler } else if (message instanceof Socks5CommandRequest) { final Socks5CommandRequest request = (Socks5CommandRequest) message; Promise promise = ctx.executor().newPromise(); - promise.addListener(future -> { - final Channel outboundChannel = future.getNow(); - if (future.isSuccess()) { - Future responseFuture = - ctx.channel().writeAndFlush(new DefaultSocks5CommandResponse( - Socks5CommandStatus.SUCCESS, - request.dstAddrType(), - request.dstAddr(), - request.dstPort())); - - responseFuture.addListener(fut -> { - ctx.pipeline().remove(this); - outboundChannel.pipeline().addLast(new RelayHandler(ctx.channel())); - ctx.pipeline().addLast(new RelayHandler(outboundChannel)); - }); - } else { + promise.asFuture().addListener(future -> { + final Channel outboundChannel = future.getNow(); + if (future.isSuccess()) { + Future responseFuture = ctx.channel().writeAndFlush(new DefaultSocks5CommandResponse( - Socks5CommandStatus.FAILURE, request.dstAddrType())); - SocksServerUtils.closeOnFlush(ctx.channel()); - } + Socks5CommandStatus.SUCCESS, + request.dstAddrType(), + request.dstAddr(), + request.dstPort())); + + responseFuture.addListener(fut -> { + ctx.pipeline().remove(this); + outboundChannel.pipeline().addLast(new RelayHandler(ctx.channel())); + ctx.pipeline().addLast(new RelayHandler(outboundChannel)); }); + } else { + ctx.channel().writeAndFlush(new DefaultSocks5CommandResponse( + Socks5CommandStatus.FAILURE, request.dstAddrType())); + SocksServerUtils.closeOnFlush(ctx.channel()); + } + }); final Channel inboundChannel = ctx.channel(); b.group(inboundChannel.executor()) diff --git a/handler-proxy/src/main/java/io/netty/handler/proxy/ProxyHandler.java b/handler-proxy/src/main/java/io/netty/handler/proxy/ProxyHandler.java index 22e3a8004a..e915577f98 100644 --- a/handler-proxy/src/main/java/io/netty/handler/proxy/ProxyHandler.java +++ b/handler-proxy/src/main/java/io/netty/handler/proxy/ProxyHandler.java @@ -109,7 +109,7 @@ public abstract class ProxyHandler implements ChannelHandler { * or the connection attempt has failed. */ public final Future connectFuture() { - return connectPromise; + return connectPromise.asFuture(); } /** @@ -396,7 +396,7 @@ public abstract class ProxyHandler implements ChannelHandler { } Promise promise = ctx.newPromise(); addPendingWrite(ctx, msg, promise); - return promise; + return promise.asFuture(); } @Override diff --git a/handler-proxy/src/test/java/io/netty/handler/proxy/HttpProxyHandlerTest.java b/handler-proxy/src/test/java/io/netty/handler/proxy/HttpProxyHandlerTest.java index ff3597feff..2d27eb924d 100644 --- a/handler-proxy/src/test/java/io/netty/handler/proxy/HttpProxyHandlerTest.java +++ b/handler-proxy/src/test/java/io/netty/handler/proxy/HttpProxyHandlerTest.java @@ -40,7 +40,6 @@ import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.proxy.HttpProxyHandler.HttpProxyConnectException; import io.netty.util.NetUtil; import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.Promise; import org.junit.jupiter.api.Test; import java.net.InetAddress; @@ -55,7 +54,6 @@ import static org.mockito.Mockito.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.same; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; public class HttpProxyHandlerTest { @@ -252,11 +250,10 @@ public class HttpProxyHandlerTest { boolean ignoreDefaultPortsInConnectHostHeader) throws Exception { InetSocketAddress proxyAddress = new InetSocketAddress(NetUtil.LOCALHOST, 8080); - Promise promise = mock(Promise.class); - verifyNoMoreInteractions(promise); + Future future = mock(Future.class); ChannelHandlerContext ctx = mock(ChannelHandlerContext.class); - when(ctx.connect(same(proxyAddress), isNull(InetSocketAddress.class))).thenReturn(promise); + when(ctx.connect(same(proxyAddress), isNull(InetSocketAddress.class))).thenReturn(future); HttpProxyHandler handler = new HttpProxyHandler( new InetSocketAddress(NetUtil.LOCALHOST, 8080), diff --git a/handler/src/main/java/io/netty/handler/address/ResolveAddressHandler.java b/handler/src/main/java/io/netty/handler/address/ResolveAddressHandler.java index fc88c16683..12b01f14d5 100644 --- a/handler/src/main/java/io/netty/handler/address/ResolveAddressHandler.java +++ b/handler/src/main/java/io/netty/handler/address/ResolveAddressHandler.java @@ -23,9 +23,9 @@ import io.netty.resolver.AddressResolverGroup; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.FutureListener; import io.netty.util.concurrent.Promise; -import io.netty.util.internal.ObjectUtil; import java.net.SocketAddress; +import java.util.Objects; /** * {@link ChannelHandler} which will resolve the {@link SocketAddress} that is passed to @@ -38,7 +38,7 @@ public class ResolveAddressHandler implements ChannelHandler { private final AddressResolverGroup resolverGroup; public ResolveAddressHandler(AddressResolverGroup resolverGroup) { - this.resolverGroup = ObjectUtil.checkNotNull(resolverGroup, "resolverGroup"); + this.resolverGroup = Objects.requireNonNull(resolverGroup, "resolverGroup"); } @Override @@ -54,9 +54,9 @@ public class ResolveAddressHandler implements ChannelHandler { } else { ctx.connect(future.getNow(), localAddress).cascadeTo(promise); } - ctx.pipeline().remove(ResolveAddressHandler.this); + ctx.pipeline().remove(this); }); - return promise; + return promise.asFuture(); } else { Future f = ctx.connect(remoteAddress, localAddress); ctx.pipeline().remove(this); diff --git a/handler/src/main/java/io/netty/handler/ssl/SniHandler.java b/handler/src/main/java/io/netty/handler/ssl/SniHandler.java index 5a4fe8d8cc..80f5a80a94 100644 --- a/handler/src/main/java/io/netty/handler/ssl/SniHandler.java +++ b/handler/src/main/java/io/netty/handler/ssl/SniHandler.java @@ -164,9 +164,9 @@ public class SniHandler extends AbstractSniHandler { try { context = mapping.map(input); } catch (Throwable cause) { - return promise.setFailure(cause); + return promise.setFailure(cause).asFuture(); } - return promise.setSuccess(context); + return promise.setSuccess(context).asFuture(); } } diff --git a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java index 4f7034d3e3..c26c596f72 100644 --- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java +++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java @@ -591,7 +591,7 @@ public class SslHandler extends ByteToMessageDecoder { * The {@link Future} for the most recent {@linkplain #renegotiate() TLS renegotiation} otherwise. */ public Future handshakeFuture() { - return handshakePromise; + return handshakePromise.asFuture(); } /** @@ -608,7 +608,7 @@ public class SslHandler extends ByteToMessageDecoder { } else { ctx.executor().execute(() -> closeOutbound0(promise)); } - return promise; + return promise.asFuture(); } private void closeOutbound0(Promise promise) { @@ -631,7 +631,7 @@ public class SslHandler extends ByteToMessageDecoder { * @see SSLEngine */ public Future sslCloseFuture() { - return sslClosePromise; + return sslClosePromise.asFuture(); } @Override @@ -700,7 +700,7 @@ public class SslHandler extends ByteToMessageDecoder { } else { Promise promise = ctx.newPromise(); pendingUnencryptedWrites.add(((ByteBufConvertible) msg).asByteBuf(), promise); - return promise; + return promise.asFuture(); } } @@ -1874,14 +1874,14 @@ public class SslHandler extends ByteToMessageDecoder { // // See https://github.com/netty/netty/issues/5931 Promise cascade = ctx.newPromise(); - cascade.cascadeTo(promise); - safeClose(ctx, closeNotifyPromise, cascade); + cascade.asFuture().cascadeTo(promise); + safeClose(ctx, closeNotifyPromise.asFuture(), cascade); } else { /// We already handling the close_notify so just attach the promise to the sslClosePromise. - sslClosePromise.addListener(future -> promise.setSuccess(null)); + sslCloseFuture().addListener(future -> promise.setSuccess(null)); } } - return promise; + return promise.asFuture(); } private void flush(ChannelHandlerContext ctx, Promise promise) { @@ -1957,15 +1957,15 @@ public class SslHandler extends ByteToMessageDecoder { EventExecutor executor = ctx.executor(); if (!executor.inEventLoop()) { executor.execute(() -> renegotiateOnEventLoop(promise)); - return promise; + return promise.asFuture(); } renegotiateOnEventLoop(promise); - return promise; + return promise.asFuture(); } private void renegotiateOnEventLoop(final Promise newHandshakePromise) { - final Promise oldHandshakePromise = handshakePromise; + Future oldHandshakePromise = handshakeFuture(); if (!oldHandshakePromise.isDone()) { // There's no need to handshake because handshake is in progress already. // Merge the new promise into the old one. @@ -2038,7 +2038,7 @@ public class SslHandler extends ByteToMessageDecoder { }, handshakeTimeoutMillis, TimeUnit.MILLISECONDS); // Cancel the handshake timeout when handshake is finished. - localHandshakePromise.addListener(f -> timeoutFuture.cancel(false)); + localHandshakePromise.asFuture().addListener(f -> timeoutFuture.cancel(false)); } private void forceFlush(ChannelHandlerContext ctx) { @@ -2102,9 +2102,11 @@ public class SslHandler extends ByteToMessageDecoder { } else { Future closeNotifyReadTimeoutFuture; - if (!sslClosePromise.isDone()) { + Future closeFuture = sslCloseFuture(); + + if (!closeFuture.isDone()) { closeNotifyReadTimeoutFuture = ctx.executor().schedule(() -> { - if (!sslClosePromise.isDone()) { + if (!closeFuture.isDone()) { logger.debug( "{} did not receive close_notify in {}ms; force-closing the connection.", ctx.channel(), closeNotifyReadTimeout); @@ -2117,8 +2119,8 @@ public class SslHandler extends ByteToMessageDecoder { closeNotifyReadTimeoutFuture = null; } - // Do the close once the we received the close_notify. - sslClosePromise.addListener(future -> { + // Do the close once we received the close_notify. + closeFuture.addListener(future -> { if (closeNotifyReadTimeoutFuture != null) { closeNotifyReadTimeoutFuture.cancel(false); } diff --git a/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java b/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java index 70494fa37b..8bf9ac01ae 100644 --- a/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java +++ b/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java @@ -116,7 +116,7 @@ public class ChunkedWriteHandler implements ChannelHandler { public Future write(ChannelHandlerContext ctx, Object msg) { Promise promise = ctx.newPromise(); queue.add(new PendingWrite(msg, promise)); - return promise; + return promise.asFuture(); } @Override @@ -150,10 +150,8 @@ public class ChunkedWriteHandler implements ChannelHandler { if (message instanceof ChunkedInput) { ChunkedInput in = (ChunkedInput) message; boolean endOfInput; - long inputLength; try { endOfInput = in.isEndOfInput(); - inputLength = in.length(); closeInput(in); } catch (Exception e) { closeInput(in); @@ -299,14 +297,10 @@ public class ChunkedWriteHandler implements ChannelHandler { private static void handleEndOfInputFuture(Future future, PendingWrite currentWrite) { ChunkedInput input = (ChunkedInput) currentWrite.msg; + closeInput(input); if (future.isFailed()) { - closeInput(input); currentWrite.fail(future.cause()); } else { - // read state of the input in local variables before closing it - long inputProgress = input.progress(); - long inputLength = input.length(); - closeInput(input); currentWrite.success(); } } diff --git a/handler/src/main/java/io/netty/handler/traffic/AbstractTrafficShapingHandler.java b/handler/src/main/java/io/netty/handler/traffic/AbstractTrafficShapingHandler.java index 2000537c19..bfdcb90530 100644 --- a/handler/src/main/java/io/netty/handler/traffic/AbstractTrafficShapingHandler.java +++ b/handler/src/main/java/io/netty/handler/traffic/AbstractTrafficShapingHandler.java @@ -563,12 +563,12 @@ public abstract class AbstractTrafficShapingHandler implements ChannelHandler { + isHandlerActive(ctx)); } submitWrite(ctx, msg, size, wait, now, promise); - return promise; + return promise.asFuture(); } } // to maintain order of write submitWrite(ctx, msg, size, 0, now, promise); - return promise; + return promise.asFuture(); } @Deprecated diff --git a/handler/src/main/java/io/netty/handler/traffic/GlobalChannelTrafficShapingHandler.java b/handler/src/main/java/io/netty/handler/traffic/GlobalChannelTrafficShapingHandler.java index b2126d8240..8a3de8743c 100644 --- a/handler/src/main/java/io/netty/handler/traffic/GlobalChannelTrafficShapingHandler.java +++ b/handler/src/main/java/io/netty/handler/traffic/GlobalChannelTrafficShapingHandler.java @@ -684,13 +684,13 @@ public class GlobalChannelTrafficShapingHandler extends AbstractTrafficShapingHa } Promise promise = ctx.newPromise(); submitWrite(ctx, msg, size, wait, now, promise); - return promise; + return promise.asFuture(); } } Promise promise = ctx.newPromise(); // to maintain order of write submitWrite(ctx, msg, size, 0, now, promise); - return promise; + return promise.asFuture(); } @Override diff --git a/handler/src/test/java/io/netty/handler/ssl/CipherSuiteCanaryTest.java b/handler/src/test/java/io/netty/handler/ssl/CipherSuiteCanaryTest.java index 2128d692cf..96e8e165a1 100644 --- a/handler/src/test/java/io/netty/handler/ssl/CipherSuiteCanaryTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/CipherSuiteCanaryTest.java @@ -35,6 +35,7 @@ import io.netty.channel.local.LocalServerChannel; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import io.netty.handler.ssl.util.SelfSignedCertificate; import io.netty.util.ReferenceCountUtil; +import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Promise; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -151,7 +152,7 @@ public class CipherSuiteCanaryTest { pipeline.addLast(new SimpleChannelInboundHandler() { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - serverPromise.cancel(true); + serverPromise.cancel(); ctx.fireChannelInactive(); } @@ -187,7 +188,7 @@ public class CipherSuiteCanaryTest { pipeline.addLast(new SimpleChannelInboundHandler() { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - clientPromise.cancel(true); + clientPromise.cancel(); ctx.fireChannelInactive(); } @@ -213,11 +214,14 @@ public class CipherSuiteCanaryTest { client.writeAndFlush(Unpooled.wrappedBuffer(new byte[] {'P', 'I', 'N', 'G'})) .syncUninterruptibly(); - assertTrue(clientPromise.await(5L, TimeUnit.SECONDS), "client timeout"); - assertTrue(serverPromise.await(5L, TimeUnit.SECONDS), "server timeout"); + Future clientFuture = clientPromise.asFuture(); + Future serverFuture = serverPromise.asFuture(); - clientPromise.sync(); - serverPromise.sync(); + assertTrue(clientFuture.await(5L, TimeUnit.SECONDS), "client timeout"); + assertTrue(serverFuture.await(5L, TimeUnit.SECONDS), "server timeout"); + + clientFuture.sync(); + serverFuture.sync(); } finally { client.close().sync(); } @@ -260,19 +264,15 @@ public class CipherSuiteCanaryTest { List dst = new ArrayList<>(); SslProvider[] sslProviders = SslProvider.values(); - for (int i = 0; i < sslProviders.length; i++) { - SslProvider serverSslProvider = sslProviders[i]; - - for (int j = 0; j < sslProviders.length; j++) { - SslProvider clientSslProvider = sslProviders[j]; - + for (SslProvider serverSslProvider : sslProviders) { + for (SslProvider clientSslProvider : sslProviders) { if ((serverSslProvider != SslProvider.JDK || clientSslProvider != SslProvider.JDK) - && !OpenSsl.isAvailable()) { + && !OpenSsl.isAvailable()) { continue; } - dst.add(new Object[]{serverSslProvider, clientSslProvider, rfcCipherName, true}); - dst.add(new Object[]{serverSslProvider, clientSslProvider, rfcCipherName, false}); + dst.add(new Object[] { serverSslProvider, clientSslProvider, rfcCipherName, true }); + dst.add(new Object[] { serverSslProvider, clientSslProvider, rfcCipherName, false }); } } diff --git a/handler/src/test/java/io/netty/handler/ssl/OpenSslPrivateKeyMethodTest.java b/handler/src/test/java/io/netty/handler/ssl/OpenSslPrivateKeyMethodTest.java index 993949ce7b..3d8229d405 100644 --- a/handler/src/test/java/io/netty/handler/ssl/OpenSslPrivateKeyMethodTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/OpenSslPrivateKeyMethodTest.java @@ -239,7 +239,7 @@ public class OpenSslPrivateKeyMethodTest { pipeline.addLast(new SimpleChannelInboundHandler() { @Override public void channelInactive(ChannelHandlerContext ctx) { - serverPromise.cancel(true); + serverPromise.cancel(); ctx.fireChannelInactive(); } @@ -275,7 +275,7 @@ public class OpenSslPrivateKeyMethodTest { pipeline.addLast(new SimpleChannelInboundHandler() { @Override public void channelInactive(ChannelHandlerContext ctx) { - clientPromise.cancel(true); + clientPromise.cancel(); ctx.fireChannelInactive(); } @@ -300,11 +300,13 @@ public class OpenSslPrivateKeyMethodTest { client.writeAndFlush(Unpooled.wrappedBuffer(new byte[] {'P', 'I', 'N', 'G'})) .syncUninterruptibly(); - assertTrue(clientPromise.await(5L, TimeUnit.SECONDS), "client timeout"); - assertTrue(serverPromise.await(5L, TimeUnit.SECONDS), "server timeout"); + Future clientFuture = clientPromise.asFuture(); + Future serverFuture = serverPromise.asFuture(); + assertTrue(clientFuture.await(5L, TimeUnit.SECONDS), "client timeout"); + assertTrue(serverFuture.await(5L, TimeUnit.SECONDS), "server timeout"); - clientPromise.sync(); - serverPromise.sync(); + clientFuture.sync(); + serverFuture.sync(); assertTrue(signCalled.get()); } finally { client.close().sync(); @@ -442,7 +444,7 @@ public class OpenSslPrivateKeyMethodTest { } catch (Throwable cause) { promise.setFailure(cause); } - return promise; + return promise.asFuture(); } @Override @@ -470,7 +472,7 @@ public class OpenSslPrivateKeyMethodTest { } catch (Throwable cause) { promise.setFailure(cause); } - return promise; + return promise.asFuture(); } } } diff --git a/handler/src/test/java/io/netty/handler/ssl/ParameterizedSslHandlerTest.java b/handler/src/test/java/io/netty/handler/ssl/ParameterizedSslHandlerTest.java index 73ccc896f4..15af2e1b78 100644 --- a/handler/src/test/java/io/netty/handler/ssl/ParameterizedSslHandlerTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/ParameterizedSslHandlerTest.java @@ -254,7 +254,7 @@ public class ParameterizedSslHandlerTest { } }).connect(sc.localAddress()).get(); - donePromise.get(); + donePromise.asFuture().sync(); } finally { if (cc != null) { cc.close().syncUninterruptibly(); @@ -355,7 +355,7 @@ public class ParameterizedSslHandlerTest { } }).connect(sc.localAddress()).get(); - promise.syncUninterruptibly(); + promise.asFuture().syncUninterruptibly(); } finally { if (cc != null) { cc.close().syncUninterruptibly(); @@ -479,8 +479,8 @@ public class ParameterizedSslHandlerTest { } }).connect(sc.localAddress()).get(); - serverPromise.awaitUninterruptibly(); - clientPromise.awaitUninterruptibly(); + serverPromise.asFuture().awaitUninterruptibly(); + clientPromise.asFuture().awaitUninterruptibly(); // Server always received the close_notify as the client triggers the close sequence. assertTrue(serverPromise.isSuccess()); diff --git a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java index 3b20c8e1ce..f1163ac806 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java @@ -1094,7 +1094,7 @@ public abstract class SSLEngineTest { Future ccf = cb.connect(new InetSocketAddress(expectedHost, port)); assertTrue(ccf.awaitUninterruptibly().isSuccess()); clientChannel = ccf.get(); - return clientWritePromise; + return clientWritePromise.asFuture(); } private void mySetupMutualAuth(SSLEngineTestParam param, File keyFile, File crtFile, String keyPassword) @@ -2000,7 +2000,7 @@ public abstract class SSLEngineTest { }).connect(serverChannel.localAddress()).get(); - promise.syncUninterruptibly(); + promise.asFuture().syncUninterruptibly(); serverCert.delete(); clientCert.delete(); @@ -4029,8 +4029,9 @@ public abstract class SSLEngineTest { out.write(1); out.flush(); - assertTrue(promise.await(10, TimeUnit.SECONDS)); - SecretKey key = promise.get(); + Future future = promise.asFuture(); + assertTrue(future.await(10, TimeUnit.SECONDS)); + SecretKey key = future.get(); assertEquals(48, key.getEncoded().length, "AES secret key must be 48 bytes"); } finally { closeQuietly(socket); diff --git a/handler/src/test/java/io/netty/handler/ssl/SniClientJava8TestUtil.java b/handler/src/test/java/io/netty/handler/ssl/SniClientJava8TestUtil.java index 79d3961392..056a906356 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SniClientJava8TestUtil.java +++ b/handler/src/test/java/io/netty/handler/ssl/SniClientJava8TestUtil.java @@ -152,7 +152,7 @@ final class SniClientJava8TestUtil { Bootstrap cb = new Bootstrap(); cc = cb.group(group).channel(LocalChannel.class).handler(sslHandler).connect(address).get(); - promise.syncUninterruptibly(); + promise.asFuture().syncUninterruptibly(); sslHandler.handshakeFuture().syncUninterruptibly(); } catch (CompletionException e) { throw e.getCause(); diff --git a/handler/src/test/java/io/netty/handler/ssl/SniClientTest.java b/handler/src/test/java/io/netty/handler/ssl/SniClientTest.java index 2f5e064d33..b5ac17d50c 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SniClientTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SniClientTest.java @@ -139,7 +139,7 @@ public class SniClientTest { SslHandler handler = new SslHandler( sslClientContext.newEngine(ByteBufAllocator.DEFAULT, sniHostName, -1)); cc = cb.group(group).channel(LocalChannel.class).handler(handler).connect(address).get(); - assertEquals(sniHostName, promise.syncUninterruptibly().getNow()); + assertEquals(sniHostName, promise.asFuture().syncUninterruptibly().getNow()); // After we are done with handshaking getHandshakeSession() should return null. handler.handshakeFuture().syncUninterruptibly(); diff --git a/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java b/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java index 13c7a1731f..a3d69c9c57 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java @@ -537,7 +537,7 @@ public class SniHandlerTest { } finally { if (!success) { ReferenceCountUtil.safeRelease(sslContext); - releasePromise.cancel(true); + releasePromise.cancel(); } } } @@ -569,7 +569,7 @@ public class SniHandlerTest { // The client disconnects cc.close().syncUninterruptibly(); - if (!releasePromise.awaitUninterruptibly(10L, TimeUnit.SECONDS)) { + if (!releasePromise.asFuture().awaitUninterruptibly(10L, TimeUnit.SECONDS)) { throw new IllegalStateException("It doesn't seem #replaceHandler() got called."); } diff --git a/handler/src/test/java/io/netty/handler/ssl/SslErrorTest.java b/handler/src/test/java/io/netty/handler/ssl/SslErrorTest.java index f93706c1b4..e8cee1bfcf 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SslErrorTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SslErrorTest.java @@ -185,7 +185,7 @@ public class SslErrorTest { } }).connect(serverChannel.localAddress()).get(); // Block until we received the correct exception - promise.syncUninterruptibly(); + promise.asFuture().syncUninterruptibly(); } finally { if (clientChannel != null) { clientChannel.close().syncUninterruptibly(); diff --git a/handler/src/test/java/io/netty/handler/ssl/SslHandlerTest.java b/handler/src/test/java/io/netty/handler/ssl/SslHandlerTest.java index 4ba6e14035..b86da5f617 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SslHandlerTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SslHandlerTest.java @@ -129,7 +129,7 @@ public class SslHandlerTest { if (((ByteBuf) msg).isReadable()) { Promise promise = ctx.newPromise(); writesToFail.add(promise); - return promise; + return promise.asFuture(); } } return ctx.newSucceededFuture(); @@ -493,8 +493,8 @@ public class SslHandlerTest { sc = serverBootstrap.bind(new InetSocketAddress(0)).get(); cc = bootstrap.connect(sc.localAddress()).get(); - serverPromise.syncUninterruptibly(); - clientPromise.syncUninterruptibly(); + serverPromise.asFuture().syncUninterruptibly(); + clientPromise.asFuture().syncUninterruptibly(); } finally { if (cc != null) { cc.close().syncUninterruptibly(); diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/Cache.java b/resolver-dns/src/main/java/io/netty/resolver/dns/Cache.java index 263d7ef4aa..515a0e7369 100644 --- a/resolver-dns/src/main/java/io/netty/resolver/dns/Cache.java +++ b/resolver-dns/src/main/java/io/netty/resolver/dns/Cache.java @@ -51,6 +51,11 @@ abstract class Cache { AtomicReferenceFieldUpdater.newUpdater(Cache.Entries.class, FutureAndDelay.class, "expirationFuture"); private static final Future CANCELLED_FUTURE = new Future() { + @Override + public boolean cancel() { + return cancel(false); + } + @Override public boolean isSuccess() { return false; diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java index e895d4e4c3..2fa6994ef6 100644 --- a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java +++ b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsNameResolver.java @@ -483,7 +483,7 @@ public class DnsNameResolver extends InetNameResolver { }); b.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(maxPayloadSize)); - channelFuture = responseHandler.channelActivePromise; + channelFuture = responseHandler.channelActivePromise.asFuture(); try { ch = b.createUnregistered(); Future future = localAddress == null ? ch.register() : ch.bind(localAddress); @@ -731,10 +731,10 @@ public class DnsNameResolver extends InetNameResolver { DnsRecord[] additionalsArray = toArray(additionals, true); try { doResolve(inetHost, additionalsArray, promise, resolveCache); - return promise; } catch (Exception e) { - return promise.setFailure(e); + promise.setFailure(e); } + return promise.asFuture(); } /** @@ -764,10 +764,10 @@ public class DnsNameResolver extends InetNameResolver { DnsRecord[] additionalsArray = toArray(additionals, true); try { doResolveAll(inetHost, additionalsArray, promise, resolveCache); - return promise; } catch (Exception e) { - return promise.setFailure(e); + promise.setFailure(e); } + return promise.asFuture(); } @Override @@ -858,7 +858,7 @@ public class DnsNameResolver extends InetNameResolver { if (!result.isEmpty()) { trySuccess(promise, result); - return promise; + return promise.asFuture(); } } } @@ -868,7 +868,7 @@ public class DnsNameResolver extends InetNameResolver { dnsServerAddressStreamProvider.nameServerAddressStream(hostname); new DnsRecordResolveContext(this, promise, question, additionals, nameServerAddrs, maxQueriesPerResolve) .resolve(promise); - return promise; + return promise.asFuture(); } private static DnsRecord[] toArray(Iterable additionals, boolean validateType) { @@ -994,7 +994,7 @@ public class DnsNameResolver extends InetNameResolver { DnsCache resolveCache, boolean completeEarlyIfPossible) { final Promise> allPromise = executor().newPromise(); doResolveAllUncached(hostname, additionals, promise, allPromise, resolveCache, true); - allPromise.addListener(future -> { + allPromise.asFuture().addListener(future -> { if (future.isSuccess()) { trySuccess(promise, future.getNow().get(0)); } else { @@ -1225,10 +1225,10 @@ public class DnsNameResolver extends InetNameResolver { try { new DatagramDnsQueryContext(this, nameServerAddr, question, additionals, castPromise) .query(flush, writePromise); - return castPromise; } catch (Exception e) { - return castPromise.setFailure(e); + castPromise.setFailure(e); } + return castPromise.asFuture(); } @SuppressWarnings("unchecked") @@ -1330,7 +1330,7 @@ public class DnsNameResolver extends InetNameResolver { } }); - promise.addListener(addressEnvelopeFuture -> { + promise.asFuture().addListener(addressEnvelopeFuture -> { channel.close(); if (addressEnvelopeFuture.isSuccess()) { diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsQueryContext.java b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsQueryContext.java index 314fbdf4ea..68c48ead87 100644 --- a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsQueryContext.java +++ b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsQueryContext.java @@ -64,7 +64,7 @@ abstract class DnsQueryContext implements FutureListener { final int initialSearchDomainIdx = startWithoutSearchDomain ? 0 : 1; final Promise> searchDomainPromise = parent.executor().newPromise(); - searchDomainPromise.addListener(new FutureListener>() { + searchDomainPromise.asFuture().addListener(new FutureListener>() { private int searchDomainIdx = initialSearchDomainIdx; @Override public void operationComplete(Future> future) { @@ -220,7 +220,7 @@ abstract class DnsResolveContext { promise.tryFailure(new SearchDomainUnknownHostException(cause, hostname)); } else if (searchDomainIdx < searchDomains.length) { Promise> newPromise = parent.executor().newPromise(); - newPromise.addListener(this); + newPromise.asFuture().addListener(this); doSearchDomainQuery(hostname + '.' + searchDomains[searchDomainIdx++], newPromise); } else if (!startWithoutSearchDomain) { internalResolve(hostname, promise); @@ -421,7 +421,7 @@ abstract class DnsResolveContext { queriesInProgress.add(f); - queryLifecycleObserver.queryWritten(nameServerAddr, writePromise); + queryLifecycleObserver.queryWritten(nameServerAddr, writePromise.asFuture()); f.addListener(future -> { queriesInProgress.remove(future); @@ -475,7 +475,7 @@ abstract class DnsResolveContext { queriesInProgress.add(resolveFuture); Promise> resolverPromise = parent.executor().newPromise(); - resolverPromise.addListener(future -> { + resolverPromise.asFuture().addListener(future -> { // Remove placeholder. queriesInProgress.remove(resolveFuture); diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/InflightNameResolver.java b/resolver-dns/src/main/java/io/netty/resolver/dns/InflightNameResolver.java index 96c0931c58..bdd671d8fe 100644 --- a/resolver-dns/src/main/java/io/netty/resolver/dns/InflightNameResolver.java +++ b/resolver-dns/src/main/java/io/netty/resolver/dns/InflightNameResolver.java @@ -61,26 +61,27 @@ final class InflightNameResolver implements NameResolver { } @Override - public Promise resolve(String inetHost, Promise promise) { + public Future resolve(String inetHost, Promise promise) { return resolve(resolvesInProgress, inetHost, promise, false); } @Override - public Promise> resolveAll(String inetHost, Promise> promise) { + public Future> resolveAll(String inetHost, Promise> promise) { return resolve(resolveAllsInProgress, inetHost, promise, true); } - private Promise resolve( + private Future resolve( final ConcurrentMap> resolveMap, final String inetHost, final Promise promise, boolean resolveAll) { final Promise earlyPromise = resolveMap.putIfAbsent(inetHost, promise); if (earlyPromise != null) { // Name resolution for the specified inetHost is in progress already. - if (earlyPromise.isDone()) { - transferResult(earlyPromise, promise); + Future earlyFuture = promise.asFuture(); + if (earlyFuture.isDone()) { + transferResult(earlyFuture, promise); } else { - earlyPromise.addListener(f -> transferResult(f, promise)); + earlyFuture.addListener(f -> transferResult(f, promise)); } } else { try { @@ -97,12 +98,12 @@ final class InflightNameResolver implements NameResolver { if (promise.isDone()) { resolveMap.remove(inetHost); } else { - promise.addListener(f -> resolveMap.remove(inetHost)); + promise.asFuture().addListener(f -> resolveMap.remove(inetHost)); } } } - return promise; + return promise.asFuture(); } private static void transferResult(Future src, Promise dst) { diff --git a/resolver-dns/src/test/java/io/netty/resolver/dns/DnsAddressResolverGroupTest.java b/resolver-dns/src/test/java/io/netty/resolver/dns/DnsAddressResolverGroupTest.java index 7cabe994f8..0d25410e08 100644 --- a/resolver-dns/src/test/java/io/netty/resolver/dns/DnsAddressResolverGroupTest.java +++ b/resolver-dns/src/test/java/io/netty/resolver/dns/DnsAddressResolverGroupTest.java @@ -55,7 +55,7 @@ public class DnsAddressResolverGroupTest { promise.setFailure(cause); } }).await(); - promise.sync(); + promise.asFuture().sync(); } finally { resolverGroup.close(); group.shutdownGracefully(); diff --git a/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java b/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java index c270831923..0867acda6a 100644 --- a/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java +++ b/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java @@ -3138,7 +3138,7 @@ public class DnsNameResolverTest { final TestDnsServer dnsServer1 = new TestDnsServer(Collections.emptySet()) { @Override protected DnsMessage filterMessage(DnsMessage message) { - promise.cancel(true); + promise.cancel(); return message; } }; diff --git a/resolver/src/main/java/io/netty/resolver/AbstractAddressResolver.java b/resolver/src/main/java/io/netty/resolver/AbstractAddressResolver.java index 9ba6dc2afd..a078b7fee3 100644 --- a/resolver/src/main/java/io/netty/resolver/AbstractAddressResolver.java +++ b/resolver/src/main/java/io/netty/resolver/AbstractAddressResolver.java @@ -104,7 +104,7 @@ public abstract class AbstractAddressResolver implement final T cast = (T) address; final Promise promise = executor().newPromise(); doResolve(cast, promise); - return promise; + return promise.asFuture(); } catch (Exception e) { return executor().newFailedFuture(e); } @@ -117,24 +117,26 @@ public abstract class AbstractAddressResolver implement if (!isSupported(address)) { // Address type not supported by the resolver - return promise.setFailure(new UnsupportedAddressTypeException()); + promise.setFailure(new UnsupportedAddressTypeException()); + return promise.asFuture(); } if (isResolved(address)) { // Resolved already; no need to perform a lookup @SuppressWarnings("unchecked") final T cast = (T) address; - return promise.setSuccess(cast); + promise.setSuccess(cast); + return promise.asFuture(); } try { @SuppressWarnings("unchecked") final T cast = (T) address; doResolve(cast, promise); - return promise; } catch (Exception e) { - return promise.setFailure(e); + promise.setFailure(e); } + return promise.asFuture(); } @Override @@ -156,7 +158,7 @@ public abstract class AbstractAddressResolver implement final T cast = (T) address; final Promise> promise = executor().newPromise(); doResolveAll(cast, promise); - return promise; + return promise.asFuture(); } catch (Exception e) { return executor().newFailedFuture(e); } @@ -169,24 +171,26 @@ public abstract class AbstractAddressResolver implement if (!isSupported(address)) { // Address type not supported by the resolver - return promise.setFailure(new UnsupportedAddressTypeException()); + promise.setFailure(new UnsupportedAddressTypeException()); + return promise.asFuture(); } if (isResolved(address)) { // Resolved already; no need to perform a lookup @SuppressWarnings("unchecked") final T cast = (T) address; - return promise.setSuccess(Collections.singletonList(cast)); + promise.setSuccess(Collections.singletonList(cast)); + return promise.asFuture(); } try { @SuppressWarnings("unchecked") final T cast = (T) address; doResolveAll(cast, promise); - return promise; } catch (Exception e) { - return promise.setFailure(e); + promise.setFailure(e); } + return promise.asFuture(); } /** diff --git a/resolver/src/main/java/io/netty/resolver/SimpleNameResolver.java b/resolver/src/main/java/io/netty/resolver/SimpleNameResolver.java index 4f781fd7e9..8bf0c27619 100644 --- a/resolver/src/main/java/io/netty/resolver/SimpleNameResolver.java +++ b/resolver/src/main/java/io/netty/resolver/SimpleNameResolver.java @@ -59,10 +59,10 @@ public abstract class SimpleNameResolver implements NameResolver { try { doResolve(inetHost, promise); - return promise; } catch (Exception e) { - return promise.setFailure(e); + promise.setFailure(e); } + return promise.asFuture(); } @Override @@ -77,10 +77,10 @@ public abstract class SimpleNameResolver implements NameResolver { try { doResolveAll(inetHost, promise); - return promise; } catch (Exception e) { - return promise.setFailure(e); + promise.setFailure(e); } + return promise.asFuture(); } /** diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/AbstractSocketReuseFdTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/AbstractSocketReuseFdTest.java index c8d68a98e9..3bcc327b31 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/AbstractSocketReuseFdTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/AbstractSocketReuseFdTest.java @@ -101,8 +101,8 @@ public abstract class AbstractSocketReuseFdTest extends AbstractSocketTest { cb.connect(sc.localAddress()).addListener(listener); } - clientDonePromise.sync(); - serverDonePromise.sync(); + clientDonePromise.asFuture().sync(); + serverDonePromise.asFuture().sync(); sc.close().sync(); if (globalException.get() != null && !(globalException.get() instanceof IOException)) { diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramConnectNotExistsTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramConnectNotExistsTest.java index d7bced7461..af5de77f80 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramConnectNotExistsTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramConnectNotExistsTest.java @@ -69,7 +69,7 @@ public class DatagramConnectNotExistsTest extends AbstractClientSocketTest { assertTrue(datagramChannel.isActive()); datagramChannel.writeAndFlush( Unpooled.copiedBuffer("test", CharsetUtil.US_ASCII)).syncUninterruptibly(); - assertTrue(promise.syncUninterruptibly().getNow() instanceof PortUnreachableException); + assertTrue(promise.asFuture().syncUninterruptibly().getNow() instanceof PortUnreachableException); } finally { if (datagramChannel != null) { datagramChannel.close(); diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketBufReleaseTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketBufReleaseTest.java index f0f44daa13..a487c25207 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketBufReleaseTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketBufReleaseTest.java @@ -22,7 +22,6 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.util.concurrent.DefaultEventExecutorGroup; -import io.netty.util.concurrent.DefaultPromise; import io.netty.util.concurrent.DefaultThreadFactory; import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.Promise; @@ -55,7 +54,7 @@ public class SocketBufReleaseTest extends AbstractSocketTest { Channel cc = cb.connect(sc.localAddress()).get(); // Ensure the server socket accepted the client connection *and* initialized pipeline successfully. - serverHandler.channelFuture.sync(); + serverHandler.channelFuture.asFuture().sync(); // and then close all sockets. sc.close().sync(); @@ -73,7 +72,7 @@ public class SocketBufReleaseTest extends AbstractSocketTest { private final Random random = new Random(); private final CountDownLatch latch = new CountDownLatch(1); private ByteBuf buf; - private final Promise channelFuture = new DefaultPromise<>(executor); + private final Promise channelFuture = executor.newPromise(); @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketConnectTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketConnectTest.java index 3bae73c5c7..c0c90cb3ba 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketConnectTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketConnectTest.java @@ -78,7 +78,7 @@ public class SocketConnectTest extends AbstractSocketTest { assertLocalAddress((InetSocketAddress) clientChannel.localAddress()); assertNotNull(clientChannel.remoteAddress()); - assertLocalAddress(localAddressPromise.get()); + assertLocalAddress(localAddressPromise.asFuture().get()); } finally { if (clientChannel != null) { clientChannel.close().syncUninterruptibly(); diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketGatheringWriteTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketGatheringWriteTest.java index ddd5155054..7b278f751c 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketGatheringWriteTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketGatheringWriteTest.java @@ -151,7 +151,7 @@ public class SocketGatheringWriteTest extends AbstractSocketTest { throw t; } - serverDonePromise.sync(); + serverDonePromise.asFuture().sync(); sh.channel.close().sync(); ch.channel.close().sync(); sc.close().sync(); diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketStringEchoTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketStringEchoTest.java index 1ac5c36a9b..7026e0ddfb 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketStringEchoTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketStringEchoTest.java @@ -111,8 +111,8 @@ public class SocketStringEchoTest extends AbstractSocketTest { cc.writeAndFlush(element + delimiter); } - ch.donePromise.sync(); - sh.donePromise.sync(); + ch.donePromise.asFuture().sync(); + sh.donePromise.asFuture().sync(); sh.channel.close().sync(); ch.channel.close().sync(); sc.close().sync(); diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/TrafficShapingHandlerTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/TrafficShapingHandlerTest.java index 49dbb349ab..8d610ca90c 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/TrafficShapingHandlerTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/TrafficShapingHandlerTest.java @@ -348,7 +348,7 @@ public class TrafficShapingHandlerTest extends AbstractSocketTest { } cc.flush(); - promise.await(); + promise.asFuture().await(); Long stop = TrafficCounter.milliSecondFromNano(); assertTrue(promise.isSuccess(), "Error during execution of TrafficShapping: " + promise.cause()); diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java index ecf70734a3..da160a626f 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java @@ -609,7 +609,7 @@ abstract class AbstractEpollChannel extends AbstractChannel implements UnixChann }, connectTimeoutMillis, TimeUnit.MILLISECONDS); } - promise.addListener(future -> { + promise.asFuture().addListener(future -> { if (future.isCancelled()) { if (connectTimeoutFuture != null) { connectTimeoutFuture.cancel(false); diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java index ee6a86679e..25a5b5a02d 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java @@ -242,7 +242,8 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im in.remove(); } return 1; - } else if (flushedAmount == 0) { + } + if (flushedAmount == 0) { validateFileRegion(region, offset); } return WRITE_STATUS_SNDBUF_FULL; @@ -437,7 +438,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im loop.execute(() -> ((AbstractUnsafe) unsafe()).shutdownOutput(promise)); } - return promise; + return promise.asFuture(); } @Override @@ -458,7 +459,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im loop.execute(() -> shutdownInput0(promise)); } } - return promise; + return promise.asFuture(); } @Override @@ -474,7 +475,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im } else { shutdownOutputFuture.addListener(promise, this::shutdownOutputDone); } - return promise; + return promise.asFuture(); } private void shutdownOutputDone(Promise promise, Future shutdownOutputFuture) { diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java index b289b26e9b..cb30cdfddf 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java @@ -149,9 +149,8 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements } return joinGroup(multicastAddress, iface, null, promise); } catch (IOException e) { - promise.setFailure(e); + return promise.setFailure(e).asFuture(); } - return promise; } @Override @@ -186,7 +185,7 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements } catch (IOException e) { promise.setFailure(e); } - return promise; + return promise.asFuture(); } @Override @@ -200,9 +199,8 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements return leaveGroup( multicastAddress, NetworkInterface.getByInetAddress(localAddress().getAddress()), null, promise); } catch (IOException e) { - promise.setFailure(e); + return promise.setFailure(e).asFuture(); } - return promise; } @Override @@ -237,7 +235,7 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements } catch (IOException e) { promise.setFailure(e); } - return promise; + return promise.asFuture(); } @Override @@ -255,7 +253,7 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements requireNonNull(sourceToBlock, "sourceToBlock"); requireNonNull(networkInterface, "networkInterface"); promise.setFailure(new UnsupportedOperationException("Multicast not supported")); - return promise; + return promise.asFuture(); } @Override @@ -274,7 +272,7 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements } catch (Throwable e) { promise.setFailure(e); } - return promise; + return promise.asFuture(); } @Override diff --git a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueChannel.java b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueChannel.java index 1db93a573e..7388c41bb6 100644 --- a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueChannel.java +++ b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueChannel.java @@ -560,7 +560,7 @@ abstract class AbstractKQueueChannel extends AbstractChannel implements UnixChan }, connectTimeoutMillis, TimeUnit.MILLISECONDS); } - promise.addListener(future -> { + promise.asFuture().addListener(future -> { if (future.isCancelled()) { if (connectTimeoutFuture != null) { connectTimeoutFuture.cancel(false); diff --git a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueStreamChannel.java b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueStreamChannel.java index f7e4efbb0a..99c9a4a8e0 100644 --- a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueStreamChannel.java +++ b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueStreamChannel.java @@ -224,7 +224,8 @@ public abstract class AbstractKQueueStreamChannel extends AbstractKQueueChannel in.remove(); } return 1; - } else if (flushedAmount == 0) { + } + if (flushedAmount == 0) { validateFileRegion(region, offset); } return WRITE_STATUS_SNDBUF_FULL; @@ -409,7 +410,7 @@ public abstract class AbstractKQueueStreamChannel extends AbstractKQueueChannel } else { loop.execute(() -> ((AbstractUnsafe) unsafe()).shutdownOutput(promise)); } - return promise; + return promise.asFuture(); } @Override @@ -425,7 +426,7 @@ public abstract class AbstractKQueueStreamChannel extends AbstractKQueueChannel } else { loop.execute(() -> shutdownInput0(promise)); } - return promise; + return promise.asFuture(); } private void shutdownInput0(Promise promise) { @@ -451,7 +452,7 @@ public abstract class AbstractKQueueStreamChannel extends AbstractKQueueChannel } else { shutdownOutputFuture.addListener(promise, this::shutdownOutputDone); } - return promise; + return promise.asFuture(); } private void shutdownOutputDone(Promise promise, Future shutdownOutputFuture) { diff --git a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/KQueueDatagramChannel.java b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/KQueueDatagramChannel.java index 0dce1c2193..9528d0b429 100644 --- a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/KQueueDatagramChannel.java +++ b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/KQueueDatagramChannel.java @@ -106,9 +106,8 @@ public final class KQueueDatagramChannel extends AbstractKQueueDatagramChannel i } return joinGroup(multicastAddress, iface, null, promise); } catch (SocketException e) { - promise.setFailure(e); + return promise.setFailure(e).asFuture(); } - return promise; } @Override @@ -138,7 +137,7 @@ public final class KQueueDatagramChannel extends AbstractKQueueDatagramChannel i requireNonNull(networkInterface, "networkInterface"); promise.setFailure(new UnsupportedOperationException("Multicast not supported")); - return promise; + return promise.asFuture(); } @Override @@ -152,9 +151,8 @@ public final class KQueueDatagramChannel extends AbstractKQueueDatagramChannel i return leaveGroup( multicastAddress, NetworkInterface.getByInetAddress(localAddress().getAddress()), null, promise); } catch (SocketException e) { - promise.setFailure(e); + return promise.setFailure(e).asFuture(); } - return promise; } @Override @@ -184,8 +182,7 @@ public final class KQueueDatagramChannel extends AbstractKQueueDatagramChannel i requireNonNull(networkInterface, "networkInterface"); promise.setFailure(new UnsupportedOperationException("Multicast not supported")); - - return promise; + return promise.asFuture(); } @Override @@ -203,7 +200,7 @@ public final class KQueueDatagramChannel extends AbstractKQueueDatagramChannel i requireNonNull(sourceToBlock, "sourceToBlock"); requireNonNull(networkInterface, "networkInterface"); promise.setFailure(new UnsupportedOperationException("Multicast not supported")); - return promise; + return promise.asFuture(); } @Override @@ -220,9 +217,8 @@ public final class KQueueDatagramChannel extends AbstractKQueueDatagramChannel i NetworkInterface.getByInetAddress(localAddress().getAddress()), sourceToBlock, promise); } catch (Throwable e) { - promise.setFailure(e); + return promise.setFailure(e).asFuture(); } - return promise; } @Override diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/nio/NioSctpChannel.java b/transport-sctp/src/main/java/io/netty/channel/sctp/nio/NioSctpChannel.java index b1c6baf4cf..521e320027 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/nio/NioSctpChannel.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/nio/NioSctpChannel.java @@ -352,7 +352,7 @@ public class NioSctpChannel extends AbstractNioMessageChannel implements io.nett } else { executor().execute(() -> bindAddress(localAddress, promise)); } - return promise; + return promise.asFuture(); } @Override @@ -372,7 +372,7 @@ public class NioSctpChannel extends AbstractNioMessageChannel implements io.nett } else { executor().execute(() -> unbindAddress(localAddress, promise)); } - return promise; + return promise.asFuture(); } private final class NioSctpChannelConfig extends DefaultSctpChannelConfig { diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/nio/NioSctpServerChannel.java b/transport-sctp/src/main/java/io/netty/channel/sctp/nio/NioSctpServerChannel.java index 05bb874225..7a87fa4ca0 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/nio/NioSctpServerChannel.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/nio/NioSctpServerChannel.java @@ -172,7 +172,7 @@ public class NioSctpServerChannel extends AbstractNioMessageChannel } else { executor().execute(() -> bindAddress(localAddress, promise)); } - return promise; + return promise.asFuture(); } @Override @@ -192,7 +192,7 @@ public class NioSctpServerChannel extends AbstractNioMessageChannel } else { executor().execute(() -> unbindAddress(localAddress, promise)); } - return promise; + return promise.asFuture(); } // Unnecessary stuff diff --git a/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java b/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java index e229e48ff0..a91ad03800 100644 --- a/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java +++ b/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java @@ -23,7 +23,6 @@ import io.netty.channel.ChannelOption; import io.netty.channel.EventLoop; import io.netty.channel.EventLoopGroup; import io.netty.util.AttributeKey; -import io.netty.util.concurrent.DefaultPromise; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Promise; import io.netty.util.internal.SocketUtils; @@ -243,12 +242,12 @@ public abstract class AbstractBootstrap, C return regFuture; } - Promise bindPromise = new DefaultPromise<>(loop); + Promise bindPromise = loop.newPromise(); if (regFuture.isDone()) { // At this point we know that the registration was complete and successful. Channel channel = regFuture.getNow(); Promise promise = channel.newPromise(); - promise.map(v -> channel).cascadeTo(bindPromise); + promise.asFuture().map(v -> channel).cascadeTo(bindPromise); doBind0(regFuture, channel, localAddress, promise); } else { // Registration future is almost always fulfilled already, but just in case it's not. @@ -261,12 +260,12 @@ public abstract class AbstractBootstrap, C } else { Channel channel = future.getNow(); Promise promise = channel.newPromise(); - promise.map(v -> channel).cascadeTo(bindPromise); + promise.asFuture().map(v -> channel).cascadeTo(bindPromise); doBind0(regFuture, channel, localAddress, promise); } }); } - return bindPromise; + return bindPromise.asFuture(); } final Future initAndRegister(EventLoop loop) { @@ -274,10 +273,10 @@ public abstract class AbstractBootstrap, C try { channel = newChannel(loop); } catch (Throwable t) { - return DefaultPromise.newFailedPromise(loop, t); + return loop.newFailedFuture(t); } - Promise promise = new DefaultPromise<>(loop); + Promise promise = loop.newPromise(); loop.execute(() -> init(channel).addListener(future -> { if (future.isSuccess()) { // TODO eventually I think we'd like to be able to either pass the generic promise down, @@ -291,7 +290,7 @@ public abstract class AbstractBootstrap, C } })); - return promise; + return promise.asFuture(); } final Channel initWithoutRegister() throws Exception { diff --git a/transport/src/main/java/io/netty/bootstrap/Bootstrap.java b/transport/src/main/java/io/netty/bootstrap/Bootstrap.java index f4e2442037..13b593d057 100644 --- a/transport/src/main/java/io/netty/bootstrap/Bootstrap.java +++ b/transport/src/main/java/io/netty/bootstrap/Bootstrap.java @@ -26,7 +26,6 @@ import io.netty.resolver.AddressResolver; import io.netty.resolver.AddressResolverGroup; import io.netty.resolver.DefaultAddressResolverGroup; import io.netty.resolver.NameResolver; -import io.netty.util.concurrent.DefaultPromise; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Promise; import io.netty.util.internal.logging.InternalLogger; @@ -187,7 +186,7 @@ public class Bootstrap extends AbstractBootstrap regFuture = initAndRegister(loop); - Promise resolveAndConnectPromise = new DefaultPromise<>(loop); + Promise resolveAndConnectPromise = loop.newPromise(); if (regFuture.isDone()) { if (regFuture.isFailed()) { return regFuture; @@ -210,7 +209,7 @@ public class Bootstrap extends AbstractBootstrap init(Channel channel) { - Promise promise = new DefaultPromise<>(channel.executor()); + Promise promise = channel.executor().newPromise(); setChannelOptions(channel, newOptionsArray(), logger); setAttributes(channel, newAttributesArray()); @@ -191,7 +190,7 @@ public class ServerBootstrap extends AbstractBootstrap) entry); + aggregatePromise.asFuture().addListener((FutureListener) entry); bufAndListenerPairs.poll(); } return result; @@ -159,7 +159,7 @@ public abstract class AbstractCoalescingBufferQueue { break; } if (entry instanceof FutureListener) { - aggregatePromise.addListener((FutureListener) entry); + aggregatePromise.asFuture().addListener((FutureListener) entry); continue; } entryBuffer = (ByteBuf) entry; diff --git a/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java b/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java index 36a8e4aad2..26820703b8 100644 --- a/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java +++ b/transport/src/main/java/io/netty/channel/DefaultChannelHandlerContext.java @@ -78,7 +78,7 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou ChannelHandler handler) { this.name = requireNonNull(name, "name"); this.pipeline = pipeline; - this.executionMask = mask(handler.getClass()); + executionMask = mask(handler.getClass()); this.handler = handler; } @@ -430,7 +430,7 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou Promise promise = newPromise(); safeExecute(executor, () -> findAndInvokeBind(localAddress).cascadeTo(promise), promise, null); - return promise; + return promise.asFuture(); } @Override @@ -446,7 +446,7 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou } Promise promise = newPromise(); safeExecute(executor, () -> findAndInvokeDeregister().cascadeTo(promise), promise, null); - return promise; + return promise.asFuture(); } private Future findAndInvokeBind(SocketAddress localAddress) { DefaultChannelHandlerContext ctx = findContextOutbound(MASK_BIND); @@ -476,7 +476,7 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou safeExecute(executor, () -> findAndInvokeConnect(remoteAddress, localAddress).cascadeTo(promise), promise, null); - return promise; + return promise.asFuture(); } private Future findAndInvokeConnect(SocketAddress remoteAddress, SocketAddress localAddress) { @@ -509,7 +509,7 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou } Promise promise = newPromise(); safeExecute(executor, () -> findAndInvokeDisconnect().cascadeTo(promise), promise, null); - return promise; + return promise.asFuture(); } private Future findAndInvokeDisconnect() { @@ -536,7 +536,7 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou } Promise promise = newPromise(); safeExecute(executor, () -> findAndInvokeClose().cascadeTo(promise), promise, null); - return promise; + return promise.asFuture(); } private Future findAndInvokeClose() { @@ -563,7 +563,7 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou } Promise promise = newPromise(); safeExecute(executor, () -> findAndInvokeRegister().cascadeTo(promise), promise, null); - return promise; + return promise.asFuture(); } private Future findAndInvokeRegister() { @@ -647,7 +647,7 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou } else { Tasks tasks = invokeTasks(); Promise promise = newPromise(); - promise.addListener(channel(), ChannelFutureListeners.FIRE_EXCEPTION_ON_FAILURE); + promise.asFuture().addListener(channel(), ChannelFutureListeners.FIRE_EXCEPTION_ON_FAILURE); // If flush throws we want to at least propagate the exception through the ChannelPipeline // as otherwise the user will not be made aware of the failure at all. safeExecute(executor, tasks.invokeFlushTask, promise, null); @@ -712,7 +712,7 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou // See https://github.com/netty/netty/issues/8343. task.cancel(); } - return promise; + return promise.asFuture(); } } @@ -820,8 +820,8 @@ final class DefaultChannelHandlerContext implements ChannelHandlerContext, Resou } } - this.prev = null; - this.next = null; + prev = null; + next = null; } @Override diff --git a/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java b/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java index c156f7239b..255ca147c6 100644 --- a/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java +++ b/transport/src/main/java/io/netty/channel/DefaultChannelPipeline.java @@ -15,11 +15,8 @@ */ package io.netty.channel; -import static java.util.Objects.requireNonNull; - import io.netty.util.ReferenceCountUtil; import io.netty.util.ResourceLeakDetector; -import io.netty.util.concurrent.DefaultPromise; import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.FastThreadLocal; import io.netty.util.concurrent.Future; @@ -42,6 +39,8 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.function.IntSupplier; import java.util.function.Predicate; +import static java.util.Objects.requireNonNull; + /** * The default {@link ChannelPipeline} implementation. It is usually created * by a {@link Channel} implementation when the {@link Channel} is created. @@ -78,7 +77,7 @@ public class DefaultChannelPipeline implements ChannelPipeline { public DefaultChannelPipeline(Channel channel) { this.channel = requireNonNull(channel, "channel"); - succeededFuture = DefaultPromise.newSuccessfulPromise(channel.executor(), null); + succeededFuture = channel.executor().newSucceededFuture(null); tail = new DefaultChannelHandlerContext(this, TAIL_NAME, TAIL_HANDLER); head = new DefaultChannelHandlerContext(this, HEAD_NAME, HEAD_HANDLER); @@ -890,7 +889,7 @@ public class DefaultChannelPipeline implements ChannelPipeline { @Override public final Promise newPromise() { - return new DefaultPromise<>(executor()); + return executor().newPromise(); } @Override @@ -900,7 +899,7 @@ public class DefaultChannelPipeline implements ChannelPipeline { @Override public final Future newFailedFuture(Throwable cause) { - return DefaultPromise.newFailedPromise(executor(), cause); + return executor().newFailedFuture(cause); } /** @@ -1045,7 +1044,7 @@ public class DefaultChannelPipeline implements ChannelPipeline { ChannelHandlerContext ctx, SocketAddress localAddress) { Promise promise = ctx.newPromise(); ctx.channel().unsafe().bind(localAddress, promise); - return promise; + return promise.asFuture(); } @Override @@ -1054,35 +1053,35 @@ public class DefaultChannelPipeline implements ChannelPipeline { SocketAddress remoteAddress, SocketAddress localAddress) { Promise promise = ctx.newPromise(); ctx.channel().unsafe().connect(remoteAddress, localAddress, promise); - return promise; + return promise.asFuture(); } @Override public Future disconnect(ChannelHandlerContext ctx) { Promise promise = ctx.newPromise(); ctx.channel().unsafe().disconnect(promise); - return promise; + return promise.asFuture(); } @Override public Future close(ChannelHandlerContext ctx) { Promise promise = ctx.newPromise(); ctx.channel().unsafe().close(promise); - return promise; + return promise.asFuture(); } @Override public Future register(ChannelHandlerContext ctx) { Promise promise = ctx.newPromise(); ctx.channel().unsafe().register(promise); - return promise; + return promise.asFuture(); } @Override public Future deregister(ChannelHandlerContext ctx) { Promise promise = ctx.newPromise(); ctx.channel().unsafe().deregister(promise); - return promise; + return promise.asFuture(); } @Override @@ -1094,7 +1093,7 @@ public class DefaultChannelPipeline implements ChannelPipeline { public Future write(ChannelHandlerContext ctx, Object msg) { Promise promise = ctx.newPromise(); ctx.channel().unsafe().write(msg, promise); - return promise; + return promise.asFuture(); } @Override diff --git a/transport/src/main/java/io/netty/channel/PendingWriteQueue.java b/transport/src/main/java/io/netty/channel/PendingWriteQueue.java index b8a46caa9a..3625068582 100644 --- a/transport/src/main/java/io/netty/channel/PendingWriteQueue.java +++ b/transport/src/main/java/io/netty/channel/PendingWriteQueue.java @@ -152,7 +152,7 @@ public final class PendingWriteQueue { p.setFailure(cause); } assertEmpty(); - return p; + return p.asFuture(); } /** diff --git a/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java b/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java index da1655374b..422816cbd0 100644 --- a/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java +++ b/transport/src/main/java/io/netty/channel/nio/AbstractNioChannel.java @@ -247,7 +247,7 @@ public abstract class AbstractNioChannel extends AbstractChannel { }, connectTimeoutMillis, TimeUnit.MILLISECONDS); } - promise.addListener(future -> { + promise.asFuture().addListener(future -> { if (future.isCancelled()) { if (connectTimeoutFuture != null) { connectTimeoutFuture.cancel(false); @@ -346,16 +346,6 @@ public abstract class AbstractNioChannel extends AbstractChannel { } } - @Override - protected void doRegister() throws Exception { - executor().unsafe().register(this); - } - - @Override - protected void doDeregister() throws Exception { - executor().unsafe().deregister(this); - } - @Override protected void doBeginRead() throws Exception { // Channel.read() or ChannelHandlerContext.read() was called diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java index 13ca31d03b..b6a639d98a 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java @@ -368,7 +368,7 @@ public final class NioDatagramChannel } catch (SocketException e) { promise.setFailure(e); } - return promise; + return promise.asFuture(); } @Override @@ -427,7 +427,7 @@ public final class NioDatagramChannel promise.setFailure(e); } - return promise; + return promise.asFuture(); } @Override @@ -443,7 +443,7 @@ public final class NioDatagramChannel } catch (SocketException e) { promise.setFailure(e); } - return promise; + return promise.asFuture(); } @Override @@ -498,7 +498,7 @@ public final class NioDatagramChannel } promise.setSuccess(null); - return promise; + return promise.asFuture(); } /** @@ -539,7 +539,7 @@ public final class NioDatagramChannel } } promise.setSuccess(null); - return promise; + return promise.asFuture(); } /** @@ -564,7 +564,7 @@ public final class NioDatagramChannel } catch (SocketException e) { promise.setFailure(e); } - return promise; + return promise.asFuture(); } void clearReadPending0() { diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java index 06aa4047c3..b96d4bd23e 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java @@ -170,7 +170,7 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty } else { loop.execute(() -> ((AbstractUnsafe) unsafe()).shutdownOutput(promise)); } - return promise; + return promise.asFuture(); } @Override @@ -191,7 +191,7 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty } else { loop.execute(() -> shutdownInput0(promise)); } - return promise; + return promise.asFuture(); } @Override @@ -207,7 +207,7 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty } else { shutdownOutputFuture.addListener(promise, this::shutdownOutputDone); } - return promise; + return promise.asFuture(); } private void shutdownOutputDone(Promise promise, Future shutdownOutputFuture) { diff --git a/transport/src/test/java/io/netty/channel/DefaultChannelPipelineTest.java b/transport/src/test/java/io/netty/channel/DefaultChannelPipelineTest.java index b96d5fd9ed..b46bf38a2e 100644 --- a/transport/src/test/java/io/netty/channel/DefaultChannelPipelineTest.java +++ b/transport/src/test/java/io/netty/channel/DefaultChannelPipelineTest.java @@ -62,7 +62,6 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; public class DefaultChannelPipelineTest { @@ -730,10 +729,10 @@ public class DefaultChannelPipelineTest { CheckEventExecutorHandler handler = new CheckEventExecutorHandler(loop); ChannelPipeline pipeline = newLocalChannel().pipeline(); pipeline.addFirst(handler); - handler.addedPromise.syncUninterruptibly(); + handler.addedFuture.syncUninterruptibly(); pipeline.channel().register(); pipeline.remove(handler); - handler.removedPromise.syncUninterruptibly(); + handler.removedFuture.syncUninterruptibly(); pipeline.channel().close().syncUninterruptibly(); } @@ -747,7 +746,7 @@ public class DefaultChannelPipelineTest { CheckEventExecutorHandler handler = new CheckEventExecutorHandler(loop); ChannelPipeline pipeline = newLocalChannel().pipeline(); pipeline.addFirst(handler); - handler.addedPromise.syncUninterruptibly(); + handler.addedFuture.syncUninterruptibly(); pipeline.channel().register(); pipeline.replace(handler, null, new ChannelHandlerAdapter() { @Override @@ -755,7 +754,7 @@ public class DefaultChannelPipelineTest { latch.countDown(); } }); - handler.removedPromise.syncUninterruptibly(); + handler.removedFuture.syncUninterruptibly(); latch.await(); pipeline.channel().close().syncUninterruptibly(); @@ -878,7 +877,7 @@ public class DefaultChannelPipelineTest { } void validate() { - validationPromise.syncUninterruptibly(); + validationPromise.asFuture().syncUninterruptibly(); validationPromise = ImmediateEventExecutor.INSTANCE.newPromise(); } } @@ -1029,7 +1028,7 @@ public class DefaultChannelPipelineTest { // This event must be captured by the added handler. pipeline.fireUserEventTriggered(event); }); - assertSame(event, promise.syncUninterruptibly().getNow()); + assertSame(event, promise.asFuture().syncUninterruptibly().getNow()); } finally { pipeline1.channel().close().syncUninterruptibly(); } @@ -1569,13 +1568,15 @@ public class DefaultChannelPipelineTest { } private static final class CallbackCheckHandler extends ChannelHandlerAdapter { - final Promise addedHandler = ImmediateEventExecutor.INSTANCE.newPromise(); - final Promise removedHandler = ImmediateEventExecutor.INSTANCE.newPromise(); + private final Promise addedHandlerPromise = ImmediateEventExecutor.INSTANCE.newPromise(); + private final Promise removedHandlerPromise = ImmediateEventExecutor.INSTANCE.newPromise(); + final Future addedHandler = addedHandlerPromise.asFuture(); + final Future removedHandler = removedHandlerPromise.asFuture(); final AtomicReference error = new AtomicReference<>(); @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - if (!addedHandler.trySuccess(true)) { + if (!addedHandlerPromise.trySuccess(true)) { error.set(new AssertionError("handlerAdded(...) called multiple times: " + ctx.name())); } else if (removedHandler.isDone() && removedHandler.getNow() == Boolean.TRUE) { error.set(new AssertionError("handlerRemoved(...) called before handlerAdded(...): " + ctx.name())); @@ -1584,7 +1585,7 @@ public class DefaultChannelPipelineTest { @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - if (!removedHandler.trySuccess(true)) { + if (!removedHandlerPromise.trySuccess(true)) { error.set(new AssertionError("handlerRemoved(...) called multiple times: " + ctx.name())); } else if (addedHandler.isDone() && addedHandler.getNow() == Boolean.FALSE) { error.set(new AssertionError("handlerRemoved(...) called before handlerAdded(...): " + ctx.name())); @@ -1594,13 +1595,17 @@ public class DefaultChannelPipelineTest { private static final class CheckEventExecutorHandler extends ChannelHandlerAdapter { final EventExecutor executor; - final Promise addedPromise; - final Promise removedPromise; + final Future addedFuture; + final Future removedFuture; + private final Promise addedPromise; + private final Promise removedPromise; CheckEventExecutorHandler(EventExecutor executor) { this.executor = executor; addedPromise = executor.newPromise(); + addedFuture = addedPromise.asFuture(); removedPromise = executor.newPromise(); + removedFuture = removedPromise.asFuture(); } @Override diff --git a/transport/src/test/java/io/netty/channel/PendingWriteQueueTest.java b/transport/src/test/java/io/netty/channel/PendingWriteQueueTest.java index 43b016ef96..9499cca8b2 100644 --- a/transport/src/test/java/io/netty/channel/PendingWriteQueueTest.java +++ b/transport/src/test/java/io/netty/channel/PendingWriteQueueTest.java @@ -209,7 +209,7 @@ public class PendingWriteQueueTest { final PendingWriteQueue queue = new PendingWriteQueue(channel.pipeline().firstContext()); Promise promise = channel.newPromise(); - promise.addListener(future -> queue.removeAndFailAll(new IllegalStateException())); + promise.asFuture().addListener(future -> queue.removeAndFailAll(new IllegalStateException())); Promise promise2 = channel.newPromise(); channel.executor().execute(() -> { @@ -239,7 +239,7 @@ public class PendingWriteQueueTest { Promise promise = channel.newPromise(); final Promise promise3 = channel.newPromise(); - promise.addListener(future -> { + promise.asFuture().addListener(future -> { queue.add(3L, promise3); }); Promise promise2 = channel.newPromise(); @@ -277,13 +277,13 @@ public class PendingWriteQueueTest { Promise promise = channel.newPromise(); final Promise promise3 = channel.newPromise(); - promise3.addListener(future -> failOrder.add(3)); - promise.addListener(future -> { + promise3.asFuture().addListener(future -> failOrder.add(3)); + promise.asFuture().addListener(future -> { failOrder.add(1); queue.add(3L, promise3); }); Promise promise2 = channel.newPromise(); - promise2.addListener(future -> failOrder.add(2)); + promise2.asFuture().addListener(future -> failOrder.add(2)); channel.executor().execute(() -> { queue.add(1L, promise); queue.add(2L, promise2); @@ -308,7 +308,7 @@ public class PendingWriteQueueTest { final PendingWriteQueue queue = new PendingWriteQueue(channel.pipeline().firstContext()); Promise promise = channel.newPromise(); - promise.addListener(future -> queue.removeAndWriteAll()); + promise.asFuture().addListener(future -> queue.removeAndWriteAll()); Promise promise2 = channel.newPromise(); channel.executor().execute(() -> { @@ -365,7 +365,7 @@ public class PendingWriteQueueTest { assertFalse(queue.isEmpty()); assertEquals(++expectedSize, queue.size()); assertNotNull(queue.current()); - return promise; + return promise.asFuture(); } @Override diff --git a/transport/src/test/java/io/netty/channel/embedded/EmbeddedChannelTest.java b/transport/src/test/java/io/netty/channel/embedded/EmbeddedChannelTest.java index 369c4b7892..43e23d69b8 100644 --- a/transport/src/test/java/io/netty/channel/embedded/EmbeddedChannelTest.java +++ b/transport/src/test/java/io/netty/channel/embedded/EmbeddedChannelTest.java @@ -343,7 +343,7 @@ public class EmbeddedChannelTest { public Future write(final ChannelHandlerContext ctx, final Object msg) { Promise promise = ctx.newPromise(); ctx.executor().execute(() -> ctx.write(msg).cascadeTo(promise)); - return promise; + return promise.asFuture(); } }); Object msg = new Object(); @@ -364,7 +364,7 @@ public class EmbeddedChannelTest { ctx.executor().schedule(() -> { ctx.writeAndFlush(msg).cascadeTo(promise); }, delay, TimeUnit.MILLISECONDS); - return promise; + return promise.asFuture(); } }); Object msg = new Object(); diff --git a/transport/src/test/java/io/netty/channel/local/LocalChannelTest.java b/transport/src/test/java/io/netty/channel/local/LocalChannelTest.java index 7cd157bf80..df86b27862 100644 --- a/transport/src/test/java/io/netty/channel/local/LocalChannelTest.java +++ b/transport/src/test/java/io/netty/channel/local/LocalChannelTest.java @@ -809,7 +809,7 @@ public class LocalChannelTest { cc.connect(sc.localAddress()).sync(); Future f = ref.get().sync(); - assertPromise.syncUninterruptibly(); + assertPromise.asFuture().syncUninterruptibly(); assertTrue(f.isSuccess()); } finally { closeChannel(cc);