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      * @deprecated Use {@link #sync()} or {@link #syncUninterruptibly()} instead.
266      */
267     @Deprecated
268     ChannelFuture rethrowIfFailed() throws Exception;
269 
270     /**
271      * Waits for this future until it is done, and rethrows the cause of the failure if this future
272      * failed.  If the cause of the failure is a checked exception, it is wrapped with a new
273      * {@link ChannelException} before being thrown.
274      */
275     ChannelFuture sync() throws InterruptedException;
276 
277     /**
278      * Waits for this future until it is done, and rethrows the cause of the failure if this future
279      * failed.  If the cause of the failure is a checked exception, it is wrapped with a new
280      * {@link ChannelException} before being thrown.
281      */
282     ChannelFuture syncUninterruptibly();
283 
284     /**
285      * Waits for this future to be completed.
286      *
287      * @throws InterruptedException
288      *         if the current thread was interrupted
289      */
290     ChannelFuture await() throws InterruptedException;
291 
292     /**
293      * Waits for this future to be completed without
294      * interruption.  This method catches an {@link InterruptedException} and
295      * discards it silently.
296      */
297     ChannelFuture awaitUninterruptibly();
298 
299     /**
300      * Waits for this future to be completed within the
301      * specified time limit.
302      *
303      * @return {@code true} if and only if the future was completed within
304      *         the specified time limit
305      *
306      * @throws InterruptedException
307      *         if the current thread was interrupted
308      */
309     boolean await(long timeout, TimeUnit unit) throws InterruptedException;
310 
311     /**
312      * Waits for this future to be completed within the
313      * specified time limit.
314      *
315      * @return {@code true} if and only if the future was completed within
316      *         the specified time limit
317      *
318      * @throws InterruptedException
319      *         if the current thread was interrupted
320      */
321     boolean await(long timeoutMillis) throws InterruptedException;
322 
323     /**
324      * Waits for this future to be completed within the
325      * specified time limit without interruption.  This method catches an
326      * {@link InterruptedException} and discards it silently.
327      *
328      * @return {@code true} if and only if the future was completed within
329      *         the specified time limit
330      */
331     boolean awaitUninterruptibly(long timeout, TimeUnit unit);
332 
333     /**
334      * Waits for this future to be completed within the
335      * specified time limit without interruption.  This method catches an
336      * {@link InterruptedException} and discards it silently.
337      *
338      * @return {@code true} if and only if the future was completed within
339      *         the specified time limit
340      */
341     boolean awaitUninterruptibly(long timeoutMillis);
342 }