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 }