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 org.jboss.netty.channel; 17 18 import java.util.concurrent.TimeUnit; 19 20 import org.jboss.netty.bootstrap.ClientBootstrap; 21 import org.jboss.netty.handler.execution.ExecutionHandler; 22 23 /** 24 * The result of an asynchronous {@link Channel} I/O operation. 25 * <p> 26 * All I/O operations in Netty are asynchronous. It means any I/O calls will 27 * return immediately with no guarantee that the requested I/O operation has 28 * been completed at the end of the call. Instead, you will be returned with 29 * a {@link ChannelFuture} instance which gives you the information about the 30 * result or status of the I/O operation. 31 * <p> 32 * A {@link ChannelFuture} is either <em>uncompleted</em> or <em>completed</em>. 33 * When an I/O operation begins, a new future object is created. The new future 34 * is uncompleted initially - it is neither succeeded, failed, nor cancelled 35 * because the I/O operation is not finished yet. If the I/O operation is 36 * finished either successfully, with failure, or by cancellation, the future is 37 * marked as completed with more specific information, such as the cause of the 38 * failure. Please note that even failure and cancellation belong to the 39 * completed state. 40 * <pre> 41 * +---------------------------+ 42 * | Completed successfully | 43 * +---------------------------+ 44 * +----> isDone() = <b>true</b> | 45 * +--------------------------+ | | isSuccess() = <b>true</b> | 46 * | Uncompleted | | +===========================+ 47 * +--------------------------+ | | Completed with failure | 48 * | isDone() = <b>false</b> | | +---------------------------+ 49 * | isSuccess() = false |----+----> isDone() = <b>true</b> | 50 * | isCancelled() = false | | | getCause() = <b>non-null</b> | 51 * | getCause() = null | | +===========================+ 52 * +--------------------------+ | | Completed by cancellation | 53 * | +---------------------------+ 54 * +----> isDone() = <b>true</b> | 55 * | isCancelled() = <b>true</b> | 56 * +---------------------------+ 57 * </pre> 58 * 59 * Various methods are provided to let you check if the I/O operation has been 60 * completed, wait for the completion, and retrieve the result of the I/O 61 * operation. It also allows you to add {@link ChannelFutureListener}s so you 62 * can get notified when the I/O operation is completed. 63 * 64 * <h3>Prefer {@link #addListener(ChannelFutureListener)} to {@link #await()}</h3> 65 * 66 * It is recommended to prefer {@link #addListener(ChannelFutureListener)} to 67 * {@link #await()} wherever possible to get notified when an I/O operation is 68 * done and to do any follow-up tasks. 69 * <p> 70 * {@link #addListener(ChannelFutureListener)} is non-blocking. It simply adds 71 * the specified {@link ChannelFutureListener} to the {@link ChannelFuture}, and 72 * I/O thread will notify the listeners when the I/O operation associated with 73 * the future is done. {@link ChannelFutureListener} yields the best 74 * performance and resource utilization because it does not block at all, but 75 * it could be tricky to implement a sequential logic if you are not used to 76 * event-driven programming. 77 * <p> 78 * By contrast, {@link #await()} is a blocking operation. Once called, the 79 * caller thread blocks until the operation is done. It is easier to implement 80 * a sequential logic with {@link #await()}, but the caller thread blocks 81 * unnecessarily until the I/O operation is done and there's relatively 82 * expensive cost of inter-thread notification. Moreover, there's a chance of 83 * dead lock in a particular circumstance, which is described below. 84 * 85 * <h3>Do not call {@link #await()} inside {@link ChannelHandler}</h3> 86 * <p> 87 * The event handler methods in {@link ChannelHandler} is often called by 88 * an I/O thread unless an {@link ExecutionHandler} is in the 89 * {@link ChannelPipeline}. If {@link #await()} is called by an event handler 90 * method, which is called by the I/O thread, the I/O operation it is waiting 91 * for might never be complete because {@link #await()} can block the I/O 92 * operation it is waiting for, which is a dead lock. 93 * <pre> 94 * // BAD - NEVER DO THIS 95 * {@code @Override} 96 * public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) { 97 * if (e.getMessage() instanceof GoodByeMessage) { 98 * {@link ChannelFuture} future = e.getChannel().close(); 99 * future.awaitUninterruptibly(); 100 * // Perform post-closure operation 101 * // ... 102 * } 103 * } 104 * 105 * // GOOD 106 * {@code @Override} 107 * public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) { 108 * if (e.getMessage() instanceof GoodByeMessage) { 109 * {@link ChannelFuture} future = e.getChannel().close(); 110 * future.addListener(new {@link ChannelFutureListener}() { 111 * public void operationComplete({@link ChannelFuture} future) { 112 * // Perform post-closure operation 113 * // ... 114 * } 115 * }); 116 * } 117 * } 118 * </pre> 119 * <p> 120 * In spite of the disadvantages mentioned above, there are certainly the cases 121 * where it is more convenient to call {@link #await()}. In such a case, please 122 * make sure you do not call {@link #await()} in an I/O thread. Otherwise, 123 * {@link IllegalStateException} will be raised to prevent a dead lock. 124 * 125 * <h3>Do not confuse I/O timeout and await timeout</h3> 126 * 127 * The timeout value you specify with {@link #await(long)}, 128 * {@link #await(long, TimeUnit)}, {@link #awaitUninterruptibly(long)}, or 129 * {@link #awaitUninterruptibly(long, TimeUnit)} are not related with I/O 130 * timeout at all. If an I/O operation times out, the future will be marked as 131 * 'completed with failure,' as depicted in the diagram above. For example, 132 * connect timeout should be configured via a transport-specific option: 133 * <pre> 134 * // BAD - NEVER DO THIS 135 * {@link ClientBootstrap} b = ...; 136 * {@link ChannelFuture} f = b.connect(...); 137 * f.awaitUninterruptibly(10, TimeUnit.SECONDS); 138 * if (f.isCancelled()) { 139 * // Connection attempt cancelled by user 140 * } else if (!f.isSuccess()) { 141 * // You might get a NullPointerException here because the future 142 * // might not be completed yet. 143 * f.getCause().printStackTrace(); 144 * } else { 145 * // Connection established successfully 146 * } 147 * 148 * // GOOD 149 * {@link ClientBootstrap} b = ...; 150 * // Configure the connect timeout option. 151 * <b>b.setOption("connectTimeoutMillis", 10000);</b> 152 * {@link ChannelFuture} f = b.connect(...); 153 * f.awaitUninterruptibly(); 154 * 155 * // Now we are sure the future is completed. 156 * assert f.isDone(); 157 * 158 * if (f.isCancelled()) { 159 * // Connection attempt cancelled by user 160 * } else if (!f.isSuccess()) { 161 * f.getCause().printStackTrace(); 162 * } else { 163 * // Connection established successfully 164 * } 165 * </pre> 166 * 167 * @apiviz.landmark 168 * @apiviz.owns org.jboss.netty.channel.ChannelFutureListener - - notifies 169 */ 170 public interface ChannelFuture { 171 172 /** 173 * Returns a channel where the I/O operation associated with this 174 * future takes place. 175 */ 176 Channel getChannel(); 177 178 /** 179 * Returns {@code true} if and only if this future is 180 * complete, regardless of whether the operation was successful, failed, 181 * or cancelled. 182 */ 183 boolean isDone(); 184 185 /** 186 * Returns {@code true} if and only if this future was 187 * cancelled by a {@link #cancel()} method. 188 */ 189 boolean isCancelled(); 190 191 /** 192 * Returns {@code true} if and only if the I/O operation was completed 193 * successfully. 194 */ 195 boolean isSuccess(); 196 197 /** 198 * Returns the cause of the failed I/O operation if the I/O operation has 199 * failed. 200 * 201 * @return the cause of the failure. 202 * {@code null} if succeeded or this future is not 203 * completed yet. 204 */ 205 Throwable getCause(); 206 207 /** 208 * Cancels the I/O operation associated with this future 209 * and notifies all listeners if canceled successfully. 210 * 211 * @return {@code true} if and only if the operation has been canceled. 212 * {@code false} if the operation can't be canceled or is already 213 * completed. 214 */ 215 boolean cancel(); 216 217 /** 218 * Marks this future as a success and notifies all 219 * listeners. 220 * 221 * @return {@code true} if and only if successfully marked this future as 222 * a success. Otherwise {@code false} because this future is 223 * already marked as either a success or a failure. 224 */ 225 boolean setSuccess(); 226 227 /** 228 * Marks this future as a failure and notifies all 229 * listeners. 230 * 231 * @return {@code true} if and only if successfully marked this future as 232 * a failure. Otherwise {@code false} because this future is 233 * already marked as either a success or a failure. 234 */ 235 boolean setFailure(Throwable cause); 236 237 /** 238 * Notifies the progress of the operation to the listeners that implements 239 * {@link ChannelFutureProgressListener}. Please note that this method will 240 * not do anything and return {@code false} if this future is complete 241 * already. 242 * 243 * @return {@code true} if and only if notification was made. 244 */ 245 boolean setProgress(long amount, long current, long total); 246 247 /** 248 * Adds the specified listener to this future. The 249 * specified listener is notified when this future is 250 * {@linkplain #isDone() done}. If this future is already 251 * completed, the specified listener is notified immediately. 252 */ 253 void addListener(ChannelFutureListener listener); 254 255 /** 256 * Removes the specified listener from this future. 257 * The specified listener is no longer notified when this 258 * future is {@linkplain #isDone() done}. If the specified 259 * listener is not associated with this future, this method 260 * does nothing and returns silently. 261 */ 262 void removeListener(ChannelFutureListener listener); 263 264 /** 265 * Waits for this future until it is done, and rethrows the cause of the failure if this future 266 * failed. If the cause of the failure is a checked exception, it is wrapped with a new 267 * {@link ChannelException} before being thrown. 268 */ 269 ChannelFuture sync() throws InterruptedException; 270 271 /** 272 * Waits for this future until it is done, and rethrows the cause of the failure if this future 273 * failed. If the cause of the failure is a checked exception, it is wrapped with a new 274 * {@link ChannelException} before being thrown. 275 */ 276 ChannelFuture syncUninterruptibly(); 277 278 /** 279 * Waits for this future to be completed. 280 * 281 * @throws InterruptedException 282 * if the current thread was interrupted 283 */ 284 ChannelFuture await() throws InterruptedException; 285 286 /** 287 * Waits for this future to be completed without 288 * interruption. This method catches an {@link InterruptedException} and 289 * discards it silently. 290 */ 291 ChannelFuture awaitUninterruptibly(); 292 293 /** 294 * Waits for this future to be completed within the 295 * specified time limit. 296 * 297 * @return {@code true} if and only if the future was completed within 298 * the specified time limit 299 * 300 * @throws InterruptedException 301 * if the current thread was interrupted 302 */ 303 boolean await(long timeout, TimeUnit unit) throws InterruptedException; 304 305 /** 306 * Waits for this future to be completed within the 307 * specified time limit. 308 * 309 * @return {@code true} if and only if the future was completed within 310 * the specified time limit 311 * 312 * @throws InterruptedException 313 * if the current thread was interrupted 314 */ 315 boolean await(long timeoutMillis) throws InterruptedException; 316 317 /** 318 * Waits for this future to be completed within the 319 * specified time limit without interruption. This method catches an 320 * {@link InterruptedException} and discards it silently. 321 * 322 * @return {@code true} if and only if the future was completed within 323 * the specified time limit 324 */ 325 boolean awaitUninterruptibly(long timeout, TimeUnit unit); 326 327 /** 328 * Waits for this future to be completed within the 329 * specified time limit without interruption. This method catches an 330 * {@link InterruptedException} and discards it silently. 331 * 332 * @return {@code true} if and only if the future was completed within 333 * the specified time limit 334 */ 335 boolean awaitUninterruptibly(long timeoutMillis); 336 }