View Javadoc

    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 }