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 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 [email protected] 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 [email protected] ChannelFuture} instance which gives you the information about the
33   * result or status of the I/O operation.
34   * <p>
35   * A [email protected] 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 [email protected] ChannelFutureListener}s so you
65   * can get notified when the I/O operation is completed.
66   *
67   * <h3>Prefer [email protected] #addListener(GenericFutureListener)} to [email protected] #await()}</h3>
68   *
69   * It is recommended to prefer [email protected] #addListener(GenericFutureListener)} to
70   * [email protected] #await()} wherever possible to get notified when an I/O operation is
71   * done and to do any follow-up tasks.
72   * <p>
73   * [email protected] #addListener(GenericFutureListener)} is non-blocking.  It simply adds
74   * the specified [email protected] ChannelFutureListener} to the [email protected] ChannelFuture}, and
75   * I/O thread will notify the listeners when the I/O operation associated with
76   * the future is done.  [email protected] 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, [email protected] #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 [email protected] #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 [email protected] #await()} inside [email protected] ChannelHandler}</h3>
89   * <p>
90   * The event handler methods in [email protected] ChannelHandler} are usually called by
91   * an I/O thread.  If [email protected] #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 [email protected] #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   * [email protected] @Override}
98   * public void channelRead([email protected] ChannelHandlerContext} ctx, Object msg) {
99   *     [email protected] ChannelFuture} future = ctx.channel().close();
100  *     future.awaitUninterruptibly();
101  *     // Perform post-closure operation
102  *     // ...
103  * }
104  *
105  * // GOOD
106  * [email protected] @Override}
107  * public void channelRead([email protected] ChannelHandlerContext} ctx, Object msg) {
108  *     [email protected] ChannelFuture} future = ctx.channel().close();
109  *     future.addListener(new [email protected] ChannelFutureListener}() {
110  *         public void operationComplete([email protected] 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 [email protected] #await()}. In such a case, please
120  * make sure you do not call [email protected] #await()} in an I/O thread.  Otherwise,
121  * [email protected] 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 [email protected] #await(long)},
126  * [email protected] #await(long, TimeUnit)}, [email protected] #awaitUninterruptibly(long)}, or
127  * [email protected] #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  * [email protected] Bootstrap} b = ...;
134  * [email protected] 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  * [email protected] Bootstrap} b = ...;
148  * // Configure the connect timeout option.
149  * <b>b.option([email protected] ChannelOption}.CONNECT_TIMEOUT_MILLIS, 10000);</b>
150  * [email protected] 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 [email protected] true} if this [email protected] ChannelFuture} is a void future and so not allow to call any of the
199      * following methods:
200      * <ul>
201      *     <li>[email protected] #addListener(GenericFutureListener)}</li>
202      *     <li>[email protected] #addListeners(GenericFutureListener[])}</li>
203      *     <li>[email protected] #await()}</li>
204      *     <li>[email protected] #await(long, TimeUnit)} ()}</li>
205      *     <li>[email protected] #await(long)} ()}</li>
206      *     <li>[email protected] #awaitUninterruptibly()}</li>
207      *     <li>[email protected] #sync()}</li>
208      *     <li>[email protected] #syncUninterruptibly()}</li>
209      * </ul>
210      */
211     boolean isVoid();
212 }