All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.netty.channel.ChannelFuture Maven / Gradle / Ivy

There is a newer version: 0.10.0
Show newest version
/*
 * Copyright 2012 The Netty Project
 *
 * 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:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package org.jboss.netty.channel;

import java.util.concurrent.TimeUnit;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.handler.execution.ExecutionHandler;

/**
 * The result of an asynchronous {@link Channel} I/O operation.
 * 

* 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 * a {@link ChannelFuture} instance which gives you the information about the * result or status of the I/O operation. *

* A {@link ChannelFuture} is either uncompleted or completed. * 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. *

 *                                      +---------------------------+
 *                                      | Completed successfully    |
 *                                      +---------------------------+
 *                                 +---->      isDone() = true      |
 * +--------------------------+    |    |   isSuccess() = true      |
 * |        Uncompleted       |    |    +===========================+
 * +--------------------------+    |    | Completed with failure    |
 * |      isDone() = false    |    |    +---------------------------+
 * |   isSuccess() = false    |----+---->   isDone() = true         |
 * | isCancelled() = false    |    |    | getCause() = non-null     |
 * |    getCause() = null     |    |    +===========================+
 * +--------------------------+    |    | Completed by cancellation |
 *                                 |    +---------------------------+
 *                                 +---->      isDone() = true      |
 *                                      | isCancelled() = true      |
 *                                      +---------------------------+
 * 
* * 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 * operation. It also allows you to add {@link ChannelFutureListener}s so you * can get notified when the I/O operation is completed. * *

Prefer {@link #addListener(ChannelFutureListener)} to {@link #await()}

* * It is recommended to prefer {@link #addListener(ChannelFutureListener)} to * {@link #await()} wherever possible to get notified when an I/O operation is * done and to do any follow-up tasks. *

* {@link #addListener(ChannelFutureListener)} is non-blocking. It simply adds * 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. *

* 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. * *

Do not call {@link #await()} inside {@link ChannelHandler}

*

* The event handler methods in {@link ChannelHandler} is often called by * an I/O thread unless an {@link ExecutionHandler} is in the * {@link ChannelPipeline}. If {@link #await()} is called by an event handler * 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. *

 * // BAD - NEVER DO THIS
 * {@code @Override}
 * public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
 *     if (e.getMessage() instanceof GoodByeMessage) {
 *         {@link ChannelFuture} future = e.getChannel().close();
 *         future.awaitUninterruptibly();
 *         // Perform post-closure operation
 *         // ...
 *     }
 * }
 *
 * // GOOD
 * {@code @Override}
 * public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
 *     if (e.getMessage() instanceof GoodByeMessage) {
 *         {@link ChannelFuture} future = e.getChannel().close();
 *         future.addListener(new {@link ChannelFutureListener}() {
 *             public void operationComplete({@link ChannelFuture} future) {
 *                 // Perform post-closure operation
 *                 // ...
 *             }
 *         });
 *     }
 * }
 * 
*

* In spite of the disadvantages mentioned above, there are certainly the cases * 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, * {@link IllegalStateException} will be raised to prevent a dead lock. * *

Do not confuse I/O timeout and await timeout

* * 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: *
 * // BAD - NEVER DO THIS
 * {@link ClientBootstrap} b = ...;
 * {@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.
 *     f.getCause().printStackTrace();
 * } else {
 *     // Connection established successfully
 * }
 *
 * // GOOD
 * {@link ClientBootstrap} b = ...;
 * // Configure the connect timeout option.
 * b.setOption("connectTimeoutMillis", 10000);
 * {@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()) {
 *     f.getCause().printStackTrace();
 * } else {
 *     // Connection established successfully
 * }
 * 
* * @apiviz.landmark * @apiviz.owns org.jboss.netty.channel.ChannelFutureListener - - notifies */ public interface ChannelFuture { /** * Returns a channel where the I/O operation associated with this * future takes place. */ Channel getChannel(); /** * Returns {@code true} if and only if this future is * complete, regardless of whether the operation was successful, failed, * or cancelled. */ boolean isDone(); /** * Returns {@code true} if and only if this future was * cancelled by a {@link #cancel()} method. */ boolean isCancelled(); /** * Returns {@code true} if and only if the I/O operation was completed * successfully. */ boolean isSuccess(); /** * Returns the cause of the failed I/O operation if the I/O operation has * failed. * * @return the cause of the failure. * {@code null} if succeeded or this future is not * completed yet. */ Throwable getCause(); /** * Cancels the I/O operation associated with this future * and notifies all listeners if canceled successfully. * * @return {@code true} if and only if the operation has been canceled. * {@code false} if the operation can't be canceled or is already * completed. */ boolean cancel(); /** * Marks this future as a success and notifies all * listeners. * * @return {@code true} if and only if successfully marked this future as * a success. Otherwise {@code false} because this future is * already marked as either a success or a failure. */ boolean setSuccess(); /** * Marks this future as a failure and notifies all * listeners. * * @return {@code true} if and only if successfully marked this future as * a failure. Otherwise {@code false} because this future is * already marked as either a success or a failure. */ boolean setFailure(Throwable cause); /** * Notifies the progress of the operation to the listeners that implements * {@link ChannelFutureProgressListener}. Please note that this method will * not do anything and return {@code false} if this future is complete * already. * * @return {@code true} if and only if notification was made. */ boolean setProgress(long amount, long current, long total); /** * Adds the specified listener to this future. The * specified listener is notified when this future is * {@linkplain #isDone() done}. If this future is already * completed, the specified listener is notified immediately. */ void addListener(ChannelFutureListener listener); /** * Removes the specified listener from this future. * The specified listener is no longer notified when this * future is {@linkplain #isDone() done}. If the specified * listener is not associated with this future, this method * does nothing and returns silently. */ void removeListener(ChannelFutureListener listener); /** * Waits for this future until it is done, and rethrows the cause of the failure if this future * failed. If the cause of the failure is a checked exception, it is wrapped with a new * {@link ChannelException} before being thrown. */ ChannelFuture sync() throws InterruptedException; /** * Waits for this future until it is done, and rethrows the cause of the failure if this future * failed. If the cause of the failure is a checked exception, it is wrapped with a new * {@link ChannelException} before being thrown. */ ChannelFuture syncUninterruptibly(); /** * Waits for this future to be completed. * * @throws InterruptedException * if the current thread was interrupted */ ChannelFuture await() throws InterruptedException; /** * Waits for this future to be completed without * interruption. This method catches an {@link InterruptedException} and * discards it silently. */ ChannelFuture awaitUninterruptibly(); /** * Waits for this future to be completed within the * specified time limit. * * @return {@code true} if and only if the future was completed within * the specified time limit * * @throws InterruptedException * if the current thread was interrupted */ boolean await(long timeout, TimeUnit unit) throws InterruptedException; /** * Waits for this future to be completed within the * specified time limit. * * @return {@code true} if and only if the future was completed within * the specified time limit * * @throws InterruptedException * if the current thread was interrupted */ boolean await(long timeoutMillis) throws InterruptedException; /** * Waits for this future to be completed within the * specified time limit without interruption. This method catches an * {@link InterruptedException} and discards it silently. * * @return {@code true} if and only if the future was completed within * the specified time limit */ boolean awaitUninterruptibly(long timeout, TimeUnit unit); /** * Waits for this future to be completed within the * specified time limit without interruption. This method catches an * {@link InterruptedException} and discards it silently. * * @return {@code true} if and only if the future was completed within * the specified time limit */ boolean awaitUninterruptibly(long timeoutMillis); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy