2008-08-08 02:37:18 +02:00
|
|
|
/*
|
2012-06-04 22:31:44 +02:00
|
|
|
* Copyright 2012 The Netty Project
|
2008-08-08 02:37:18 +02:00
|
|
|
*
|
2011-12-09 06:18:34 +01:00
|
|
|
* The Netty Project licenses this file to you under the Apache License,
|
|
|
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
|
|
* with the License. You may obtain a copy of the License at:
|
2008-08-08 02:37:18 +02:00
|
|
|
*
|
2012-06-04 22:31:44 +02:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2008-08-08 03:27:24 +02:00
|
|
|
*
|
2009-08-28 09:15:49 +02:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
2011-12-09 06:18:34 +01:00
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
2009-08-28 09:15:49 +02:00
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
2008-08-08 02:37:18 +02:00
|
|
|
*/
|
2011-12-09 04:38:59 +01:00
|
|
|
package io.netty.channel;
|
2008-08-08 02:37:18 +02:00
|
|
|
|
2012-12-23 20:58:49 +01:00
|
|
|
import io.netty.bootstrap.Bootstrap;
|
2013-03-05 21:41:19 +01:00
|
|
|
import io.netty.util.concurrent.BlockingOperationException;
|
|
|
|
import io.netty.util.concurrent.Future;
|
|
|
|
import io.netty.util.concurrent.GenericFutureListener;
|
2012-12-23 20:58:49 +01:00
|
|
|
|
2013-02-14 21:09:16 +01:00
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
2012-12-23 20:58:49 +01:00
|
|
|
|
2008-08-08 02:37:18 +02:00
|
|
|
/**
|
2008-09-24 12:46:58 +02:00
|
|
|
* The result of an asynchronous {@link Channel} I/O operation.
|
|
|
|
* <p>
|
|
|
|
* All I/O operations in Netty are asynchronous. It means any I/O calls will
|
|
|
|
* return immediately with no guarantee that the requested I/O operation has
|
|
|
|
* been completed at the end of the call. Instead, you will be returned with
|
2010-02-16 12:55:44 +01:00
|
|
|
* a {@link ChannelFuture} instance which gives you the information about the
|
|
|
|
* result or status of the I/O operation.
|
2008-09-24 12:46:58 +02:00
|
|
|
* <p>
|
2010-02-16 12:55:44 +01:00
|
|
|
* A {@link ChannelFuture} is either <em>uncompleted</em> or <em>completed</em>.
|
|
|
|
* When an I/O operation begins, a new future object is created. The new future
|
|
|
|
* is uncompleted initially - it is neither succeeded, failed, nor cancelled
|
|
|
|
* because the I/O operation is not finished yet. If the I/O operation is
|
|
|
|
* finished either successfully, with failure, or by cancellation, the future is
|
|
|
|
* marked as completed with more specific information, such as the cause of the
|
|
|
|
* failure. Please note that even failure and cancellation belong to the
|
|
|
|
* completed state.
|
|
|
|
* <pre>
|
|
|
|
* +---------------------------+
|
|
|
|
* | Completed successfully |
|
|
|
|
* +---------------------------+
|
|
|
|
* +----> isDone() = <b>true</b> |
|
|
|
|
* +--------------------------+ | | isSuccess() = <b>true</b> |
|
|
|
|
* | Uncompleted | | +===========================+
|
|
|
|
* +--------------------------+ | | Completed with failure |
|
|
|
|
* | isDone() = <b>false</b> | | +---------------------------+
|
|
|
|
* | isSuccess() = false |----+----> isDone() = <b>true</b> |
|
2013-05-02 13:22:31 +02:00
|
|
|
* | isCancelled() = false | | | cause() = <b>non-null</b> |
|
|
|
|
* | cause() = null | | +===========================+
|
2010-02-16 12:55:44 +01:00
|
|
|
* +--------------------------+ | | Completed by cancellation |
|
|
|
|
* | +---------------------------+
|
|
|
|
* +----> isDone() = <b>true</b> |
|
|
|
|
* | isCancelled() = <b>true</b> |
|
|
|
|
* +---------------------------+
|
|
|
|
* </pre>
|
|
|
|
*
|
2008-09-24 12:46:58 +02:00
|
|
|
* Various methods are provided to let you check if the I/O operation has been
|
|
|
|
* completed, wait for the completion, and retrieve the result of the I/O
|
2010-02-16 12:55:44 +01:00
|
|
|
* operation. It also allows you to add {@link ChannelFutureListener}s so you
|
|
|
|
* can get notified when the I/O operation is completed.
|
2008-08-08 02:37:18 +02:00
|
|
|
*
|
2013-03-05 21:41:19 +01:00
|
|
|
* <h3>Prefer {@link #addListener(GenericFutureListener)} to {@link #await()}</h3>
|
2009-04-08 11:37:47 +02:00
|
|
|
*
|
2013-03-05 21:41:19 +01:00
|
|
|
* It is recommended to prefer {@link #addListener(GenericFutureListener)} to
|
2009-04-08 11:37:47 +02:00
|
|
|
* {@link #await()} wherever possible to get notified when an I/O operation is
|
|
|
|
* done and to do any follow-up tasks.
|
|
|
|
* <p>
|
2013-03-05 21:41:19 +01:00
|
|
|
* {@link #addListener(GenericFutureListener)} is non-blocking. It simply adds
|
2009-04-08 11:37:47 +02:00
|
|
|
* the specified {@link ChannelFutureListener} to the {@link ChannelFuture}, and
|
|
|
|
* I/O thread will notify the listeners when the I/O operation associated with
|
|
|
|
* the future is done. {@link ChannelFutureListener} yields the best
|
|
|
|
* performance and resource utilization because it does not block at all, but
|
|
|
|
* it could be tricky to implement a sequential logic if you are not used to
|
|
|
|
* event-driven programming.
|
|
|
|
* <p>
|
|
|
|
* By contrast, {@link #await()} is a blocking operation. Once called, the
|
|
|
|
* caller thread blocks until the operation is done. It is easier to implement
|
|
|
|
* a sequential logic with {@link #await()}, but the caller thread blocks
|
|
|
|
* unnecessarily until the I/O operation is done and there's relatively
|
|
|
|
* expensive cost of inter-thread notification. Moreover, there's a chance of
|
|
|
|
* dead lock in a particular circumstance, which is described below.
|
|
|
|
*
|
|
|
|
* <h3>Do not call {@link #await()} inside {@link ChannelHandler}</h3>
|
|
|
|
* <p>
|
2011-12-28 11:44:04 +01:00
|
|
|
* The event handler methods in {@link ChannelHandler} is usually called by
|
|
|
|
* an I/O thread. If {@link #await()} is called by an event handler
|
2009-04-08 11:37:47 +02:00
|
|
|
* method, which is called by the I/O thread, the I/O operation it is waiting
|
|
|
|
* for might never be complete because {@link #await()} can block the I/O
|
|
|
|
* operation it is waiting for, which is a dead lock.
|
|
|
|
* <pre>
|
|
|
|
* // BAD - NEVER DO THIS
|
2010-02-02 03:00:04 +01:00
|
|
|
* {@code @Override}
|
2013-07-09 16:09:28 +02:00
|
|
|
* public void channelRead({@link ChannelHandlerContext} ctx, GoodByeMessage msg) {
|
2012-12-23 20:58:49 +01:00
|
|
|
* {@link ChannelFuture} future = ctx.channel().close();
|
|
|
|
* future.awaitUninterruptibly();
|
|
|
|
* // Perform post-closure operation
|
|
|
|
* // ...
|
2009-04-08 11:37:47 +02:00
|
|
|
* }
|
|
|
|
*
|
|
|
|
* // GOOD
|
2010-02-02 03:00:04 +01:00
|
|
|
* {@code @Override}
|
2013-07-09 16:09:28 +02:00
|
|
|
* public void channelRead({@link ChannelHandlerContext} ctx, GoodByeMessage msg) {
|
2012-12-23 20:58:49 +01:00
|
|
|
* {@link ChannelFuture} future = ctx.channel().close();
|
|
|
|
* future.addListener(new {@link ChannelFutureListener}() {
|
|
|
|
* public void operationComplete({@link ChannelFuture} future) {
|
|
|
|
* // Perform post-closure operation
|
|
|
|
* // ...
|
|
|
|
* }
|
|
|
|
* });
|
2009-04-08 11:37:47 +02:00
|
|
|
* }
|
|
|
|
* </pre>
|
2009-04-23 13:45:23 +02:00
|
|
|
* <p>
|
2009-04-28 15:35:55 +02:00
|
|
|
* In spite of the disadvantages mentioned above, there are certainly the cases
|
2009-04-23 13:45:23 +02:00
|
|
|
* where it is more convenient to call {@link #await()}. In such a case, please
|
|
|
|
* make sure you do not call {@link #await()} in an I/O thread. Otherwise,
|
2012-12-23 20:58:49 +01:00
|
|
|
* {@link BlockingOperationException} will be raised to prevent a dead lock.
|
2009-04-08 11:37:47 +02:00
|
|
|
*
|
2010-02-16 12:55:44 +01:00
|
|
|
* <h3>Do not confuse I/O timeout and await timeout</h3>
|
|
|
|
*
|
|
|
|
* The timeout value you specify with {@link #await(long)},
|
|
|
|
* {@link #await(long, TimeUnit)}, {@link #awaitUninterruptibly(long)}, or
|
|
|
|
* {@link #awaitUninterruptibly(long, TimeUnit)} are not related with I/O
|
|
|
|
* timeout at all. If an I/O operation times out, the future will be marked as
|
|
|
|
* 'completed with failure,' as depicted in the diagram above. For example,
|
|
|
|
* connect timeout should be configured via a transport-specific option:
|
|
|
|
* <pre>
|
|
|
|
* // BAD - NEVER DO THIS
|
2012-09-12 14:04:41 +02:00
|
|
|
* {@link Bootstrap} b = ...;
|
2010-02-16 12:55:44 +01:00
|
|
|
* {@link ChannelFuture} f = b.connect(...);
|
|
|
|
* f.awaitUninterruptibly(10, TimeUnit.SECONDS);
|
|
|
|
* if (f.isCancelled()) {
|
|
|
|
* // Connection attempt cancelled by user
|
|
|
|
* } else if (!f.isSuccess()) {
|
|
|
|
* // You might get a NullPointerException here because the future
|
|
|
|
* // might not be completed yet.
|
2013-05-02 13:22:31 +02:00
|
|
|
* f.cause().printStackTrace();
|
2010-02-16 12:55:44 +01:00
|
|
|
* } else {
|
|
|
|
* // Connection established successfully
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* // GOOD
|
2012-09-12 14:04:41 +02:00
|
|
|
* {@link Bootstrap} b = ...;
|
2010-02-16 12:55:44 +01:00
|
|
|
* // Configure the connect timeout option.
|
2012-12-23 20:58:49 +01:00
|
|
|
* <b>b.setOption({@link ChannelOption}.CONNECT_TIMEOUT_MILLIS, 10000);</b>
|
2010-02-16 12:55:44 +01:00
|
|
|
* {@link ChannelFuture} f = b.connect(...);
|
|
|
|
* f.awaitUninterruptibly();
|
|
|
|
*
|
|
|
|
* // Now we are sure the future is completed.
|
|
|
|
* assert f.isDone();
|
|
|
|
*
|
|
|
|
* if (f.isCancelled()) {
|
|
|
|
* // Connection attempt cancelled by user
|
|
|
|
* } else if (!f.isSuccess()) {
|
2013-05-02 13:22:31 +02:00
|
|
|
* f.cause().printStackTrace();
|
2010-02-16 12:55:44 +01:00
|
|
|
* } else {
|
|
|
|
* // Connection established successfully
|
|
|
|
* }
|
|
|
|
* </pre>
|
2008-08-08 02:37:18 +02:00
|
|
|
*/
|
2013-03-18 14:18:31 +01:00
|
|
|
public interface ChannelFuture extends Future<Void> {
|
2008-08-11 09:33:19 +02:00
|
|
|
|
|
|
|
/**
|
2008-09-24 11:48:32 +02:00
|
|
|
* Returns a channel where the I/O operation associated with this
|
2008-10-02 07:02:46 +02:00
|
|
|
* future takes place.
|
2008-08-11 09:33:19 +02:00
|
|
|
*/
|
2012-05-01 10:19:41 +02:00
|
|
|
Channel channel();
|
2008-08-08 02:37:18 +02:00
|
|
|
|
2013-03-05 21:41:19 +01:00
|
|
|
@Override
|
2013-06-12 01:00:54 +02:00
|
|
|
ChannelFuture addListener(GenericFutureListener<? extends Future<? super Void>> listener);
|
2008-08-11 09:33:19 +02:00
|
|
|
|
2013-03-05 21:41:19 +01:00
|
|
|
@Override
|
2013-06-12 01:00:54 +02:00
|
|
|
ChannelFuture addListeners(GenericFutureListener<? extends Future<? super Void>>... listeners);
|
2008-08-11 09:33:19 +02:00
|
|
|
|
2013-03-05 21:41:19 +01:00
|
|
|
@Override
|
2013-06-12 01:00:54 +02:00
|
|
|
ChannelFuture removeListener(GenericFutureListener<? extends Future<? super Void>> listener);
|
2008-08-08 02:37:18 +02:00
|
|
|
|
2013-03-05 21:41:19 +01:00
|
|
|
@Override
|
2013-06-12 01:00:54 +02:00
|
|
|
ChannelFuture removeListeners(GenericFutureListener<? extends Future<? super Void>>... listeners);
|
2008-08-11 09:33:19 +02:00
|
|
|
|
2013-03-05 21:41:19 +01:00
|
|
|
@Override
|
2012-05-14 16:57:23 +02:00
|
|
|
ChannelFuture sync() throws InterruptedException;
|
2008-08-08 02:37:18 +02:00
|
|
|
|
2013-03-05 21:41:19 +01:00
|
|
|
@Override
|
2012-05-14 16:57:23 +02:00
|
|
|
ChannelFuture syncUninterruptibly();
|
2012-01-19 05:33:37 +01:00
|
|
|
|
2013-03-05 21:41:19 +01:00
|
|
|
@Override
|
2008-08-08 02:37:18 +02:00
|
|
|
ChannelFuture await() throws InterruptedException;
|
2008-08-11 09:33:19 +02:00
|
|
|
|
2013-03-05 21:41:19 +01:00
|
|
|
@Override
|
2008-08-08 02:37:18 +02:00
|
|
|
ChannelFuture awaitUninterruptibly();
|
|
|
|
}
|