View Javadoc

    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.group;
    17
    18  import java.util.Iterator;
    19  import java.util.concurrent.TimeUnit;
    20
    21  import org.jboss.netty.channel.Channel;
    22  import org.jboss.netty.channel.ChannelFuture;
    23  import org.jboss.netty.channel.ChannelHandler;
    24  import org.jboss.netty.channel.ChannelHandlerContext;
    25  import org.jboss.netty.channel.ChannelPipeline;
    26  import org.jboss.netty.channel.MessageEvent;
    27  import org.jboss.netty.handler.execution.ExecutionHandler;
    28
    29  /**
    30   * The result of an asynchronous {@link ChannelGroup} operation.
    31   * {@link ChannelGroupFuture} is composed of {@link ChannelFuture}s which
    32   * represent the outcome of the individual I/O operations that affect the
    33   * {@link Channel}s in the {@link ChannelGroup}.
    34   *
    35   * <p>
    36   * All I/O operations in {@link ChannelGroup} are asynchronous.  It means any
    37   * I/O calls will return immediately with no guarantee that the requested I/O
    38   * operations have been completed at the end of the call.  Instead, you will be
    39   * returned with a {@link ChannelGroupFuture} instance which tells you when the
    40   * requested I/O operations have succeeded, failed, or cancelled.
    41   * <p>
    42   * Various methods are provided to let you check if the I/O operations has been
    43   * completed, wait for the completion, and retrieve the result of the I/O
    44   * operation. It also allows you to add more than one
    45   * {@link ChannelGroupFutureListener} so you can get notified when the I/O
    46   * operation have been completed.
    47   *
    48   * <h3>Prefer {@link #addListener(ChannelGroupFutureListener)} to {@link #await()}</h3>
    49   *
    50   * It is recommended to prefer {@link #addListener(ChannelGroupFutureListener)} to
    51   * {@link #await()} wherever possible to get notified when I/O operations are
    52   * done and to do any follow-up tasks.
    53   * <p>
    54   * {@link #addListener(ChannelGroupFutureListener)} is non-blocking.  It simply
    55   * adds the specified {@link ChannelGroupFutureListener} to the
    56   * {@link ChannelGroupFuture}, and I/O thread will notify the listeners when
    57   * the I/O operations associated with the future is done.
    58   * {@link ChannelGroupFutureListener} yields the best performance and resource
    59   * utilization because it does not block at all, but it could be tricky to
    60   * implement a sequential logic if you are not used to event-driven programming.
    61   * <p>
    62   * By contrast, {@link #await()} is a blocking operation.  Once called, the
    63   * caller thread blocks until all I/O operations are done.  It is easier to
    64   * implement a sequential logic with {@link #await()}, but the caller thread
    65   * blocks unnecessarily until all I/O operations are done and there's relatively
    66   * expensive cost of inter-thread notification.  Moreover, there's a chance of
    67   * dead lock in a particular circumstance, which is described below.
    68   *
    69   * <h3>Do not call {@link #await()} inside {@link ChannelHandler}</h3>
    70   * <p>
    71   * The event handler methods in {@link ChannelHandler} is often called by
    72   * an I/O thread unless an {@link ExecutionHandler} is in the
    73   * {@link ChannelPipeline}.  If {@link #await()} is called by an event handler
    74   * method, which is called by the I/O thread, the I/O operation it is waiting
    75   * for might never be complete because {@link #await()} can block the I/O
    76   * operation it is waiting for, which is a dead lock.
    77   * <pre>
    78   * // BAD - NEVER DO THIS
    79   * {@code @Override}
    80   * public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
    81   *     if (e.getMessage() instanceof ShutdownMessage) {
    82   *         {@link ChannelGroup} allChannels = MyServer.getAllChannels();
    83   *         {@link ChannelGroupFuture} future = allChannels.close();
    84   *         future.awaitUninterruptibly();
    85   *         // Perform post-shutdown operation
    86   *         // ...
    87   *     }
    88   * }
    89   *
    90   * // GOOD
    91   * {@code @Override}
    92   * public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
    93   *     if (e.getMessage() instanceof ShutdownMessage) {
    94   *         {@link ChannelGroup} allChannels = MyServer.getAllChannels();
    95   *         {@link ChannelGroupFuture} future = allChannels.close();
    96   *         future.addListener(new {@link ChannelGroupFutureListener}() {
    97   *             public void operationComplete({@link ChannelGroupFuture} future) {
    98   *                 // Perform post-closure operation
    99   *                 // ...
    100  *             }
    101  *         });
    102  *     }
    103  * }
    104  * </pre>
    105  * <p>
    106  * In spite of the disadvantages mentioned above, there are certainly the cases
    107  * where it is more convenient to call {@link #await()}. In such a case, please
    108  * make sure you do not call {@link #await()} in an I/O thread.  Otherwise,
    109  * {@link IllegalStateException} will be raised to prevent a dead lock.
    110  * @apiviz.owns org.jboss.netty.channel.group.ChannelGroupFutureListener - - notifies
    111  */
    112 public interface ChannelGroupFuture extends Iterable<ChannelFuture> {
    113
    114     /**
    115      * Returns the {@link ChannelGroup} which is associated with this future.
    116      */
    117     ChannelGroup getGroup();
    118
    119     /**
    120      * Returns the {@link ChannelFuture} of the individual I/O operation which
    121      * is associated with the {@link Channel} whose ID matches the specified
    122      * integer.
    123      *
    124      * @return the matching {@link ChannelFuture} if found.
    125      *         {@code null} otherwise.
    126      */
    127     ChannelFuture find(Integer channelId);
    128
    129     /**
    130      * Returns the {@link ChannelFuture} of the individual I/O operation which
    131      * is associated with the specified {@link Channel}.
    132      *
    133      * @return the matching {@link ChannelFuture} if found.
    134      *         {@code null} otherwise.
    135      */
    136     ChannelFuture find(Channel channel);
    137
    138     /**
    139      * Returns {@code true} if and only if this future is
    140      * complete, regardless of whether the operation was successful, failed,
    141      * or canceled.
    142      */
    143     boolean isDone();
    144
    145     /**
    146      * Returns {@code true} if and only if all I/O operations associated with
    147      * this future were successful without any failure.
    148      */
    149     boolean isCompleteSuccess();
    150
    151     /**
    152      * Returns {@code true} if and only if the I/O operations associated with
    153      * this future were partially successful with some failure.
    154      */
    155     boolean isPartialSuccess();
    156
    157     /**
    158      * Returns {@code true} if and only if all I/O operations associated with
    159      * this future have failed without any success.
    160      */
    161     boolean isCompleteFailure();
    162
    163     /**
    164      * Returns {@code true} if and only if the I/O operations associated with
    165      * this future have failed partially with some success.
    166      */
    167     boolean isPartialFailure();
    168
    169     /**
    170      * Adds the specified listener to this future.  The
    171      * specified listener is notified when this future is
    172      * {@linkplain #isDone() done}.  If this future is already
    173      * completed, the specified listener is notified immediately.
    174      */
    175     void addListener(ChannelGroupFutureListener listener);
    176
    177     /**
    178      * Removes the specified listener from this future.
    179      * The specified listener is no longer notified when this
    180      * future is {@linkplain #isDone() done}.  If this
    181      * future is already completed, this method has no effect
    182      * and returns silently.
    183      */
    184     void removeListener(ChannelGroupFutureListener listener);
    185
    186     /**
    187      * Waits for this future to be completed.
    188      *
    189      * @throws InterruptedException
    190      *         if the current thread was interrupted
    191      */
    192     ChannelGroupFuture await() throws InterruptedException;
    193
    194     /**
    195      * Waits for this future to be completed without
    196      * interruption.  This method catches an {@link InterruptedException} and
    197      * discards it silently.
    198      */
    199     ChannelGroupFuture awaitUninterruptibly();
    200
    201     /**
    202      * Waits for this future to be completed within the
    203      * specified time limit.
    204      *
    205      * @return {@code true} if and only if the future was completed within
    206      *         the specified time limit
    207      *
    208      * @throws InterruptedException
    209      *         if the current thread was interrupted
    210      */
    211     boolean await(long timeout, TimeUnit unit) throws InterruptedException;
    212
    213     /**
    214      * Waits for this future to be completed within the
    215      * specified time limit.
    216      *
    217      * @return {@code true} if and only if the future was completed within
    218      *         the specified time limit
    219      *
    220      * @throws InterruptedException
    221      *         if the current thread was interrupted
    222      */
    223     boolean await(long timeoutMillis) throws InterruptedException;
    224
    225     /**
    226      * Waits for this future to be completed within the
    227      * specified time limit without interruption.  This method catches an
    228      * {@link InterruptedException} and discards it silently.
    229      *
    230      * @return {@code true} if and only if the future was completed within
    231      *         the specified time limit
    232      */
    233     boolean awaitUninterruptibly(long timeout, TimeUnit unit);
    234
    235     /**
    236      * Waits for this future to be completed within the
    237      * specified time limit without interruption.  This method catches an
    238      * {@link InterruptedException} and discards it silently.
    239      *
    240      * @return {@code true} if and only if the future was completed within
    241      *         the specified time limit
    242      */
    243     boolean awaitUninterruptibly(long timeoutMillis);
    244
    245     /**
    246      * Returns the {@link Iterator} that enumerates all {@link ChannelFuture}s
    247      * which are associated with this future.  Please note that the returned
    248      * {@link Iterator} is is unmodifiable, which means a {@link ChannelFuture}
    249      * cannot be removed from this future.
    250      */
    251     Iterator<ChannelFuture> iterator();
    252 }