/*
 * JBoss, Home of Professional Open Source
 *
 * Copyright 2008 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed 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.xnio;

import java.util.EventListener;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.CancellationException;
import java.io.IOException;

The future result of an asynchronous request. Use instances of this interface to retrieve the final status of an asynchronous operation.

It is recommended, due to the vagaries of the way generics work, that when you use IoFuture instances, you use a wildcard to express the return type. This enables you to take advantage of covariance to retrofit more specific types later on without breaking anything.

For example, if you have a method which returns a future InputStream, you might be tempted to declare it like this:
IoFuture<InputStream> getFutureInputStream();
Now if you later decide that what you really need is a DataInputStream (which extends InputStream), you're in trouble because you have written IoFuture&lt;InputStream&gt; everywhere, which cannot be assigned to or from an IoFuture&lt;DataInputStream&gt;.

On the other hand, if you declare it like this:
IoFuture<? extends InputStream> getFutureInputStream();
Now you can change it at any time to IoFuture&lt;? extends DataInputStream&gt; without breaking the contract, since it will be assignable to variables of type IoFuture&lt;? extends InputStream&gt;.
Type parameters:
  • <T> – the type of result that this operation produces
@apiviz.landmark
/** * The future result of an asynchronous request. Use instances of this interface to retrieve the final status of * an asynchronous operation. * <p/> * It is recommended, due to the vagaries of the way generics work, that when you use {@code IoFuture} instances, you * use a wildcard to express the return type. This enables you to take advantage of covariance to retrofit * more specific types later on without breaking anything. * <p/> * For example, if you have a method which returns a future {@code InputStream}, you might be tempted to declare it like * this: * <tt><pre> * IoFuture&lt;InputStream&gt; getFutureInputStream(); * </pre></tt> * Now if you later decide that what you really need is a {@code DataInputStream} (which extends {@code InputStream}), * you're in trouble because you have written {@code IoFuture&lt;InputStream&gt;} everywhere, which cannot be assigned to or from * an {@code IoFuture&lt;DataInputStream&gt;}. * <p/> * On the other hand, if you declare it like this: * <tt><pre> * IoFuture&lt;? extends InputStream&gt; getFutureInputStream(); * </pre></tt> * Now you can change it at any time to {@code IoFuture&lt;? extends DataInputStream&gt;} without breaking the contract, since * it will be assignable to variables of type {@code IoFuture&lt;? extends InputStream&gt;}. * * @param <T> the type of result that this operation produces * * @apiviz.landmark */
public interface IoFuture<T> extends Cancellable {
The current status of an asynchronous operation.
@apiviz.exclude
/** * The current status of an asynchronous operation. * * @apiviz.exclude */
enum Status {
The operation is still in progress.
/** * The operation is still in progress. */
WAITING,
The operation has completed successfully.
/** * The operation has completed successfully. */
DONE,
The operation was cancelled.
/** * The operation was cancelled. */
CANCELLED,
The operation did not succeed.
/** * The operation did not succeed. */
FAILED, }
{@inheritDoc}
/** {@inheritDoc} */
IoFuture<T> cancel();
Get the current status.
Returns:the current status
/** * Get the current status. * * @return the current status */
Status getStatus();
Wait for the operation to complete. This method will block until the status changes from Status.WAITING.
Returns:the new status
/** * Wait for the operation to complete. This method will block until the status changes from {@link Status#WAITING}. * * @return the new status */
Status await();
Wait for the operation to complete, with a timeout. This method will block until the status changes from Status.WAITING, or the given time elapses. If the time elapses before the operation is complete, Status.WAITING is returned.
Params:
  • time – the amount of time to wait
  • timeUnit – the time unit
Returns:the new status, or Status.WAITING if the timeout expired
/** * Wait for the operation to complete, with a timeout. This method will block until the status changes from {@link Status#WAITING}, * or the given time elapses. If the time elapses before the operation is complete, {@link Status#WAITING} is * returned. * * @param time the amount of time to wait * @param timeUnit the time unit * @return the new status, or {@link Status#WAITING} if the timeout expired */
Status await(long time, TimeUnit timeUnit);
Wait for the operation to complete. This method will block until the status changes from Status.WAITING, or the current thread is interrupted.
Throws:
Returns:the new status
/** * Wait for the operation to complete. This method will block until the status changes from {@link Status#WAITING}, * or the current thread is interrupted. * * @return the new status * @throws InterruptedException if the operation is interrupted */
Status awaitInterruptibly() throws InterruptedException;
Wait for the operation to complete, with a timeout. This method will block until the status changes from Status.WAITING, the given time elapses, or the current thread is interrupted. If the time elapses before the operation is complete, Status.WAITING is returned.
Params:
  • time – the amount of time to wait
  • timeUnit – the time unit
Throws:
Returns:the new status, or Status.WAITING if the timeout expired
/** * Wait for the operation to complete, with a timeout. This method will block until the status changes from {@link Status#WAITING}, * the given time elapses, or the current thread is interrupted. If the time elapses before the operation is complete, {@link Status#WAITING} is * returned. * * @param time the amount of time to wait * @param timeUnit the time unit * @return the new status, or {@link Status#WAITING} if the timeout expired * @throws InterruptedException if the operation is interrupted */
Status awaitInterruptibly(long time, TimeUnit timeUnit) throws InterruptedException;
Get the result of the operation. If the operation is not complete, blocks until the operation completes. If the operation fails, or has already failed at the time this method is called, the failure reason is thrown.
Throws:
Returns:the result of the operation
/** * Get the result of the operation. If the operation is not complete, blocks until the operation completes. If * the operation fails, or has already failed at the time this method is called, the failure reason is thrown. * * @return the result of the operation * @throws IOException if the operation failed * @throws CancellationException if the operation was cancelled */
T get() throws IOException, CancellationException;
Get the result of the operation. If the operation is not complete, blocks until the operation completes. If the operation fails, or has already failed at the time this method is called, the failure reason is thrown. If the current thread is interrupted while waiting, an exception is thrown.
Throws:
Returns:the result of the operation
/** * Get the result of the operation. If the operation is not complete, blocks until the operation completes. If * the operation fails, or has already failed at the time this method is called, the failure reason is thrown. If * the current thread is interrupted while waiting, an exception is thrown. * * @return the result of the operation * @throws IOException if the operation failed * @throws InterruptedException if the operation is interrupted * @throws CancellationException if the operation was cancelled */
T getInterruptibly() throws IOException, InterruptedException, CancellationException;
Get the failure reason.
Throws:
Returns:the failure reason
/** * Get the failure reason. * * @return the failure reason * @throws IllegalStateException if the operation did not fail */
IOException getException() throws IllegalStateException;
Add a notifier to be called when this operation is complete. If the operation is already complete, the notifier is called immediately, possibly in the caller's thread. The given attachment is provided to the notifier.
Params:
  • notifier – the notifier to be called
  • attachment – the attachment to pass in to the notifier
Type parameters:
  • <A> – the attachment type
Returns:this instance
/** * Add a notifier to be called when this operation is complete. If the operation is already complete, the notifier * is called immediately, possibly in the caller's thread. The given attachment is provided to the notifier. * * @param notifier the notifier to be called * @param attachment the attachment to pass in to the notifier * @param <A> the attachment type * @return this instance */
<A> IoFuture<T> addNotifier(Notifier<? super T, A> notifier, A attachment);
A notifier that handles changes in the status of an IoFuture.
Type parameters:
  • <T> – the type of result that the associated future operation produces
  • <A> – the attachment type
@apiviz.exclude
/** * A notifier that handles changes in the status of an {@code IoFuture}. * * @param <T> the type of result that the associated future operation produces * @param <A> the attachment type * @apiviz.exclude */
interface Notifier<T, A> extends EventListener {
Receive notification of the completion of an outstanding operation.
Params:
  • ioFuture – the future corresponding to this operation
  • attachment – the attachment
/** * Receive notification of the completion of an outstanding operation. * * @param ioFuture the future corresponding to this operation * @param attachment the attachment */
void notify(IoFuture<? extends T> ioFuture, final A attachment); }
A base notifier class that calls the designated handler method on notification. Use this class to reduce boilerplate for standard Notifier implementations.
Type parameters:
  • <T> – the type of result that the associated future operation produces
  • <A> – the attachment type
Since:1.1
@apiviz.exclude
/** * A base notifier class that calls the designated handler method on notification. Use this class to reduce * boilerplate for standard {@link org.xnio.IoFuture.Notifier} implementations. * * @param <T> the type of result that the associated future operation produces * @param <A> the attachment type * * @since 1.1 * * @apiviz.exclude */
abstract class HandlingNotifier<T, A> implements Notifier<T, A> {
{@inheritDoc}
/** * {@inheritDoc} */
public void notify(final IoFuture<? extends T> future, A attachment) { switch (future.getStatus()) { case CANCELLED: handleCancelled(attachment); break; case DONE: try { handleDone(future.get(), attachment); } catch (IOException e) { // not possible throw new IllegalStateException(); } break; case FAILED: handleFailed(future.getException(), attachment); break; default: // not possible throw new IllegalStateException(); } }
Handle cancellation.
Params:
  • attachment – the attachment
/** * Handle cancellation. * * @param attachment the attachment */
public void handleCancelled(final A attachment) { }
Handle failure.
Params:
  • exception – the failure reason
  • attachment – the attachment
/** * Handle failure. * * @param exception the failure reason * @param attachment the attachment */
public void handleFailed(final IOException exception, final A attachment) { }
Handle completion.
Params:
  • data – the result
  • attachment – the attachment
/** * Handle completion. * * @param data the result * @param attachment the attachment */
public void handleDone(final T data, final A attachment) { } } }