1 /* 2 * Copyright 2012 The Netty Project 3 * 4 * The Netty Project licenses this file to you under the Apache License, 5 * version 2.0 (the "License"); you may not use this file except in compliance 6 * with the License. You may obtain a copy of the License at: 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations 14 * under the License. 15 */ 16 package io.netty.channel; 17 18 import io.netty.bootstrap.Bootstrap; 19 import io.netty.util.concurrent.BlockingOperationException; 20 import io.netty.util.concurrent.Future; 21 import io.netty.util.concurrent.GenericFutureListener; 22 23 import java.util.concurrent.TimeUnit; 24 25 26 /** 27 * The result of an asynchronous {@link Channel} I/O operation. 28 * <p> 29 * All I/O operations in Netty are asynchronous. It means any I/O calls will 30 * return immediately with no guarantee that the requested I/O operation has 31 * been completed at the end of the call. Instead, you will be returned with 32 * a {@link ChannelFuture} instance which gives you the information about the 33 * result or status of the I/O operation. 34 * <p> 35 * A {@link ChannelFuture} is either <em>uncompleted</em> or <em>completed</em>. 36 * When an I/O operation begins, a new future object is created. The new future 37 * is uncompleted initially - it is neither succeeded, failed, nor cancelled 38 * because the I/O operation is not finished yet. If the I/O operation is 39 * finished either successfully, with failure, or by cancellation, the future is 40 * marked as completed with more specific information, such as the cause of the 41 * failure. Please note that even failure and cancellation belong to the 42 * completed state. 43 * <pre> 44 * +---------------------------+ 45 * | Completed successfully | 46 * +---------------------------+ 47 * +----> isDone() = true | 48 * +--------------------------+ | | isSuccess() = true | 49 * | Uncompleted | | +===========================+ 50 * +--------------------------+ | | Completed with failure | 51 * | isDone() = false | | +---------------------------+ 52 * | isSuccess() = false |----+----> isDone() = true | 53 * | isCancelled() = false | | | cause() = non-null | 54 * | cause() = null | | +===========================+ 55 * +--------------------------+ | | Completed by cancellation | 56 * | +---------------------------+ 57 * +----> isDone() = true | 58 * | isCancelled() = true | 59 * +---------------------------+ 60 * </pre> 61 * 62 * Various methods are provided to let you check if the I/O operation has been 63 * completed, wait for the completion, and retrieve the result of the I/O 64 * operation. It also allows you to add {@link ChannelFutureListener}s so you 65 * can get notified when the I/O operation is completed. 66 * 67 * <h3>Prefer {@link #addListener(GenericFutureListener)} to {@link #await()}</h3> 68 * 69 * It is recommended to prefer {@link #addListener(GenericFutureListener)} to 70 * {@link #await()} wherever possible to get notified when an I/O operation is 71 * done and to do any follow-up tasks. 72 * <p> 73 * {@link #addListener(GenericFutureListener)} is non-blocking. It simply adds 74 * the specified {@link ChannelFutureListener} to the {@link ChannelFuture}, and 75 * I/O thread will notify the listeners when the I/O operation associated with 76 * the future is done. {@link ChannelFutureListener} yields the best 77 * performance and resource utilization because it does not block at all, but 78 * it could be tricky to implement a sequential logic if you are not used to 79 * event-driven programming. 80 * <p> 81 * By contrast, {@link #await()} is a blocking operation. Once called, the 82 * caller thread blocks until the operation is done. It is easier to implement 83 * a sequential logic with {@link #await()}, but the caller thread blocks 84 * unnecessarily until the I/O operation is done and there's relatively 85 * expensive cost of inter-thread notification. Moreover, there's a chance of 86 * dead lock in a particular circumstance, which is described below. 87 * 88 * <h3>Do not call {@link #await()} inside {@link ChannelHandler}</h3> 89 * <p> 90 * The event handler methods in {@link ChannelHandler} are usually called by 91 * an I/O thread. If {@link #await()} is called by an event handler 92 * method, which is called by the I/O thread, the I/O operation it is waiting 93 * for might never complete because {@link #await()} can block the I/O 94 * operation it is waiting for, which is a dead lock. 95 * <pre> 96 * // BAD - NEVER DO THIS 97 * {@code @Override} 98 * public void channelRead({@link ChannelHandlerContext} ctx, Object msg) { 99 * {@link ChannelFuture} future = ctx.channel().close(); 100 * future.awaitUninterruptibly(); 101 * // Perform post-closure operation 102 * // ... 103 * } 104 * 105 * // GOOD 106 * {@code @Override} 107 * public void channelRead({@link ChannelHandlerContext} ctx, Object msg) { 108 * {@link ChannelFuture} future = ctx.channel().close(); 109 * future.addListener(new {@link ChannelFutureListener}() { 110 * public void operationComplete({@link ChannelFuture} future) { 111 * // Perform post-closure operation 112 * // ... 113 * } 114 * }); 115 * } 116 * </pre> 117 * <p> 118 * In spite of the disadvantages mentioned above, there are certainly the cases 119 * where it is more convenient to call {@link #await()}. In such a case, please 120 * make sure you do not call {@link #await()} in an I/O thread. Otherwise, 121 * {@link BlockingOperationException} will be raised to prevent a dead lock. 122 * 123 * <h3>Do not confuse I/O timeout and await timeout</h3> 124 * 125 * The timeout value you specify with {@link #await(long)}, 126 * {@link #await(long, TimeUnit)}, {@link #awaitUninterruptibly(long)}, or 127 * {@link #awaitUninterruptibly(long, TimeUnit)} are not related with I/O 128 * timeout at all. If an I/O operation times out, the future will be marked as 129 * 'completed with failure,' as depicted in the diagram above. For example, 130 * connect timeout should be configured via a transport-specific option: 131 * <pre> 132 * // BAD - NEVER DO THIS 133 * {@link Bootstrap} b = ...; 134 * {@link ChannelFuture} f = b.connect(...); 135 * f.awaitUninterruptibly(10, TimeUnit.SECONDS); 136 * if (f.isCancelled()) { 137 * // Connection attempt cancelled by user 138 * } else if (!f.isSuccess()) { 139 * // You might get a NullPointerException here because the future 140 * // might not be completed yet. 141 * f.cause().printStackTrace(); 142 * } else { 143 * // Connection established successfully 144 * } 145 * 146 * // GOOD 147 * {@link Bootstrap} b = ...; 148 * // Configure the connect timeout option. 149 * <b>b.option({@link ChannelOption}.CONNECT_TIMEOUT_MILLIS, 10000);</b> 150 * {@link ChannelFuture} f = b.connect(...); 151 * f.awaitUninterruptibly(); 152 * 153 * // Now we are sure the future is completed. 154 * assert f.isDone(); 155 * 156 * if (f.isCancelled()) { 157 * // Connection attempt cancelled by user 158 * } else if (!f.isSuccess()) { 159 * f.cause().printStackTrace(); 160 * } else { 161 * // Connection established successfully 162 * } 163 * </pre> 164 */ 165 public interface ChannelFuture extends Future<Void> { 166 167 /** 168 * Returns a channel where the I/O operation associated with this 169 * future takes place. 170 */ 171 Channel channel(); 172 173 @Override 174 ChannelFuture addListener(GenericFutureListener<? extends Future<? super Void>> listener); 175 176 @Override 177 ChannelFuture addListeners(GenericFutureListener<? extends Future<? super Void>>... listeners); 178 179 @Override 180 ChannelFuture removeListener(GenericFutureListener<? extends Future<? super Void>> listener); 181 182 @Override 183 ChannelFuture removeListeners(GenericFutureListener<? extends Future<? super Void>>... listeners); 184 185 @Override 186 ChannelFuture sync() throws InterruptedException; 187 188 @Override 189 ChannelFuture syncUninterruptibly(); 190 191 @Override 192 ChannelFuture await() throws InterruptedException; 193 194 @Override 195 ChannelFuture awaitUninterruptibly(); 196 }