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 }