1 /* 2 * Copyright 2009 Red Hat, Inc. 3 * 4 * Red Hat licenses this file to you under the Apache License, version 2.0 5 * (the "License"); you may not use this file except in compliance with the 6 * 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 * @author <a href="http://www.jboss.org/netty/">The Netty Project</a> 168 * @author <a href="http://gleamynode.net/">Trustin Lee</a> 169 * 170 * @version $Rev: 2192 $, $Date: 2010-02-19 18:58:38 +0900 (Fri, 19 Feb 2010) $ 171 * 172 * @apiviz.landmark 173 * @apiviz.owns org.jboss.netty.channel.ChannelFutureListener - - notifies 174 */ 175 public interface ChannelFuture { 176 177 /** 178 * Returns a channel where the I/O operation associated with this 179 * future takes place. 180 */ 181 Channel getChannel(); 182 183 /** 184 * Returns {@code true} if and only if this future is 185 * complete, regardless of whether the operation was successful, failed, 186 * or cancelled. 187 */ 188 boolean isDone(); 189 190 /** 191 * Returns {@code true} if and only if this future was 192 * cancelled by a {@link #cancel()} method. 193 */ 194 boolean isCancelled(); 195 196 /** 197 * Returns {@code true} if and only if the I/O operation was completed 198 * successfully. 199 */ 200 boolean isSuccess(); 201 202 /** 203 * Returns the cause of the failed I/O operation if the I/O operation has 204 * failed. 205 * 206 * @return the cause of the failure. 207 * {@code null} if succeeded or this future is not 208 * completed yet. 209 */ 210 Throwable getCause(); 211 212 /** 213 * Cancels the I/O operation associated with this future 214 * and notifies all listeners if canceled successfully. 215 * 216 * @return {@code true} if and only if the operation has been canceled. 217 * {@code false} if the operation can't be canceled or is already 218 * completed. 219 */ 220 boolean cancel(); 221 222 /** 223 * Marks this future as a success and notifies all 224 * listeners. 225 * 226 * @return {@code true} if and only if successfully marked this future as 227 * a success. Otherwise {@code false} because this future is 228 * already marked as either a success or a failure. 229 */ 230 boolean setSuccess(); 231 232 /** 233 * Marks this future as a failure and notifies all 234 * listeners. 235 * 236 * @return {@code true} if and only if successfully marked this future as 237 * a failure. Otherwise {@code false} because this future is 238 * already marked as either a success or a failure. 239 */ 240 boolean setFailure(Throwable cause); 241 242 /** 243 * Notifies the progress of the operation to the listeners that implements 244 * {@link ChannelFutureProgressListener}. Please note that this method will 245 * not do anything and return {@code false} if this future is complete 246 * already. 247 * 248 * @return {@code true} if and only if notification was made. 249 */ 250 boolean setProgress(long amount, long current, long total); 251 252 /** 253 * Adds the specified listener to this future. The 254 * specified listener is notified when this future is 255 * {@linkplain #isDone() done}. If this future is already 256 * completed, the specified listener is notified immediately. 257 */ 258 void addListener(ChannelFutureListener listener); 259 260 /** 261 * Removes the specified listener from this future. 262 * The specified listener is no longer notified when this 263 * future is {@linkplain #isDone() done}. If the specified 264 * listener is not associated with this future, this method 265 * does nothing and returns silently. 266 */ 267 void removeListener(ChannelFutureListener listener); 268 269 /** 270 * Waits for this future to be completed. 271 * 272 * @throws InterruptedException 273 * if the current thread was interrupted 274 */ 275 ChannelFuture await() throws InterruptedException; 276 277 /** 278 * Waits for this future to be completed without 279 * interruption. This method catches an {@link InterruptedException} and 280 * discards it silently. 281 */ 282 ChannelFuture awaitUninterruptibly(); 283 284 /** 285 * Waits for this future to be completed within the 286 * specified time limit. 287 * 288 * @return {@code true} if and only if the future was completed within 289 * the specified time limit 290 * 291 * @throws InterruptedException 292 * if the current thread was interrupted 293 */ 294 boolean await(long timeout, TimeUnit unit) throws InterruptedException; 295 296 /** 297 * Waits for this future to be completed within the 298 * specified time limit. 299 * 300 * @return {@code true} if and only if the future was completed within 301 * the specified time limit 302 * 303 * @throws InterruptedException 304 * if the current thread was interrupted 305 */ 306 boolean await(long timeoutMillis) throws InterruptedException; 307 308 /** 309 * Waits for this future to be completed within the 310 * specified time limit without interruption. This method catches an 311 * {@link InterruptedException} and discards it silently. 312 * 313 * @return {@code true} if and only if the future was completed within 314 * the specified time limit 315 */ 316 boolean awaitUninterruptibly(long timeout, TimeUnit unit); 317 318 /** 319 * Waits for this future to be completed within the 320 * specified time limit without interruption. This method catches an 321 * {@link InterruptedException} and discards it silently. 322 * 323 * @return {@code true} if and only if the future was completed within 324 * the specified time limit 325 */ 326 boolean awaitUninterruptibly(long timeoutMillis); 327 }