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;
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 }