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 * https://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 io.netty.channel;
17
18 import io.netty.bootstrap.Bootstrap;
19 import io.netty.util.concurrent.BlockingOperationException;
20 import io.netty.util.concurrent.Future;
21 import io.netty.util.concurrent.GenericFutureListener;
22
23 import java.util.concurrent.TimeUnit;
24
25
26 /**
27 * The result of an asynchronous {@link Channel} I/O operation.
28 * <p>
29 * All I/O operations in Netty are asynchronous. It means any I/O calls will
30 * return immediately with no guarantee that the requested I/O operation has
31 * been completed at the end of the call. Instead, you will be returned with
32 * a {@link ChannelFuture} instance which gives you the information about the
33 * result or status of the I/O operation.
34 * <p>
35 * A {@link ChannelFuture} is either <em>uncompleted</em> or <em>completed</em>.
36 * When an I/O operation begins, a new future object is created. The new future
37 * is uncompleted initially - it is neither succeeded, failed, nor cancelled
38 * because the I/O operation is not finished yet. If the I/O operation is
39 * finished either successfully, with failure, or by cancellation, the future is
40 * marked as completed with more specific information, such as the cause of the
41 * failure. Please note that even failure and cancellation belong to the
42 * completed state.
43 * <pre>
44 * +---------------------------+
45 * | Completed successfully |
46 * +---------------------------+
47 * +----> isDone() = true |
48 * +--------------------------+ | | isSuccess() = true |
49 * | Uncompleted | | +===========================+
50 * +--------------------------+ | | Completed with failure |
51 * | isDone() = false | | +---------------------------+
52 * | isSuccess() = false |----+----> isDone() = true |
53 * | isCancelled() = false | | | cause() = non-null |
54 * | cause() = null | | +===========================+
55 * +--------------------------+ | | Completed by cancellation |
56 * | +---------------------------+
57 * +----> isDone() = true |
58 * | isCancelled() = true |
59 * +---------------------------+
60 * </pre>
61 *
62 * Various methods are provided to let you check if the I/O operation has been
63 * completed, wait for the completion, and retrieve the result of the I/O
64 * operation. It also allows you to add {@link ChannelFutureListener}s so you
65 * can get notified when the I/O operation is completed.
66 *
67 * <h3>Prefer {@link #addListener(GenericFutureListener)} to {@link #await()}</h3>
68 *
69 * It is recommended to prefer {@link #addListener(GenericFutureListener)} to
70 * {@link #await()} wherever possible to get notified when an I/O operation is
71 * done and to do any follow-up tasks.
72 * <p>
73 * {@link #addListener(GenericFutureListener)} is non-blocking. It simply adds
74 * the specified {@link ChannelFutureListener} to the {@link ChannelFuture}, and
75 * I/O thread will notify the listeners when the I/O operation associated with
76 * the future is done. {@link ChannelFutureListener} yields the best
77 * performance and resource utilization because it does not block at all, but
78 * it could be tricky to implement a sequential logic if you are not used to
79 * event-driven programming.
80 * <p>
81 * By contrast, {@link #await()} is a blocking operation. Once called, the
82 * caller thread blocks until the operation is done. It is easier to implement
83 * a sequential logic with {@link #await()}, but the caller thread blocks
84 * unnecessarily until the I/O operation is done and there's relatively
85 * expensive cost of inter-thread notification. Moreover, there's a chance of
86 * dead lock in a particular circumstance, which is described below.
87 *
88 * <h3>Do not call {@link #await()} inside {@link ChannelHandler}</h3>
89 * <p>
90 * The event handler methods in {@link ChannelHandler} are usually called by
91 * an I/O thread. If {@link #await()} is called by an event handler
92 * method, which is called by the I/O thread, the I/O operation it is waiting
93 * for might never complete because {@link #await()} can block the I/O
94 * operation it is waiting for, which is a dead lock.
95 * <pre>
96 * // BAD - NEVER DO THIS
97 * {@code @Override}
98 * public void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
99 * {@link ChannelFuture} future = ctx.channel().close();
100 * future.awaitUninterruptibly();
101 * // Perform post-closure operation
102 * // ...
103 * }
104 *
105 * // GOOD
106 * {@code @Override}
107 * public void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
108 * {@link ChannelFuture} future = ctx.channel().close();
109 * future.addListener(new {@link ChannelFutureListener}() {
110 * public void operationComplete({@link ChannelFuture} future) {
111 * // Perform post-closure operation
112 * // ...
113 * }
114 * });
115 * }
116 * </pre>
117 * <p>
118 * In spite of the disadvantages mentioned above, there are certainly the cases
119 * where it is more convenient to call {@link #await()}. In such a case, please
120 * make sure you do not call {@link #await()} in an I/O thread. Otherwise,
121 * {@link BlockingOperationException} will be raised to prevent a dead lock.
122 *
123 * <h3>Do not confuse I/O timeout and await timeout</h3>
124 *
125 * The timeout value you specify with {@link #await(long)},
126 * {@link #await(long, TimeUnit)}, {@link #awaitUninterruptibly(long)}, or
127 * {@link #awaitUninterruptibly(long, TimeUnit)} are not related with I/O
128 * timeout at all. If an I/O operation times out, the future will be marked as
129 * 'completed with failure,' as depicted in the diagram above. For example,
130 * connect timeout should be configured via a transport-specific option:
131 * <pre>
132 * // BAD - NEVER DO THIS
133 * {@link Bootstrap} b = ...;
134 * {@link ChannelFuture} f = b.connect(...);
135 * f.awaitUninterruptibly(10, TimeUnit.SECONDS);
136 * if (f.isCancelled()) {
137 * // Connection attempt cancelled by user
138 * } else if (!f.isSuccess()) {
139 * // You might get a NullPointerException here because the future
140 * // might not be completed yet.
141 * f.cause().printStackTrace();
142 * } else {
143 * // Connection established successfully
144 * }
145 *
146 * // GOOD
147 * {@link Bootstrap} b = ...;
148 * // Configure the connect timeout option.
149 * <b>b.option({@link ChannelOption}.CONNECT_TIMEOUT_MILLIS, 10000);</b>
150 * {@link ChannelFuture} f = b.connect(...);
151 * f.awaitUninterruptibly();
152 *
153 * // Now we are sure the future is completed.
154 * assert f.isDone();
155 *
156 * if (f.isCancelled()) {
157 * // Connection attempt cancelled by user
158 * } else if (!f.isSuccess()) {
159 * f.cause().printStackTrace();
160 * } else {
161 * // Connection established successfully
162 * }
163 * </pre>
164 */
165 public interface ChannelFuture extends Future<Void> {
166
167 /**
168 * Returns a channel where the I/O operation associated with this
169 * future takes place.
170 */
171 Channel channel();
172
173 @Override
174 ChannelFuture addListener(GenericFutureListener<? extends Future<? super Void>> listener);
175
176 @Override
177 ChannelFuture addListeners(GenericFutureListener<? extends Future<? super Void>>... listeners);
178
179 @Override
180 ChannelFuture removeListener(GenericFutureListener<? extends Future<? super Void>> listener);
181
182 @Override
183 ChannelFuture removeListeners(GenericFutureListener<? extends Future<? super Void>>... listeners);
184
185 @Override
186 ChannelFuture sync() throws InterruptedException;
187
188 @Override
189 ChannelFuture syncUninterruptibly();
190
191 @Override
192 ChannelFuture await() throws InterruptedException;
193
194 @Override
195 ChannelFuture awaitUninterruptibly();
196
197 /**
198 * Returns {@code true} if this {@link ChannelFuture} is a void future and so not allow to call any of the
199 * following methods:
200 * <ul>
201 * <li>{@link #addListener(GenericFutureListener)}</li>
202 * <li>{@link #addListeners(GenericFutureListener[])}</li>
203 * <li>{@link #await()}</li>
204 * <li>{@link #await(long, TimeUnit)} ()}</li>
205 * <li>{@link #await(long)} ()}</li>
206 * <li>{@link #awaitUninterruptibly()}</li>
207 * <li>{@link #sync()}</li>
208 * <li>{@link #syncUninterruptibly()}</li>
209 * </ul>
210 */
211 boolean isVoid();
212 }