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 }