Skip to content

Commit

Permalink
[JBTHR-18] AsyncFuture and friends
Browse files Browse the repository at this point in the history
  • Loading branch information
dmlloyd committed Dec 6, 2010
1 parent 1715642 commit df7e3b9
Show file tree
Hide file tree
Showing 3 changed files with 597 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/main/java/org/jboss/threads/AsyncCancellable.java
@@ -0,0 +1,41 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.threads;

/**
* An interface which supports asynchronous cancellation.
*
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
*/
public interface AsyncCancellable {

/**
* Handle an asynchronous cancellation. Does not block, and may be called more than once;
* in particular, this method may be re-invoked to set the {@code interruptionDesired} flag
* even if it has already been called without that flag set before. Otherwise, this method is
* idempotent, and thus may be called more than once without additional effect.
*
* @param interruptionDesired {@code true} if interruption of threads is desired
*/
void asyncCancel(boolean interruptionDesired);
}
210 changes: 210 additions & 0 deletions src/main/java/org/jboss/threads/AsyncFuture.java
@@ -0,0 +1,210 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.threads;

import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
* This interface represents the result of an asynchronous future task, which provides all the features
* of {@link Future} while also adding several additional convenience methods and the ability to add asynchronous
* callbacks.
*
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
*/
public interface AsyncFuture<T> extends Future<T>, AsyncCancellable {

/**
* Wait if necessary for this operation to complete, returning the outcome. The outcome will be one of
* {@link Status#COMPLETE}, {@link Status#CANCELLED}, or {@link Status#FAILED}.
*
* @return the outcome
* @throws InterruptedException if execution was interrupted while waiting
*/
Status await() throws InterruptedException;

/**
* Wait if necessary for this operation to complete, returning the outcome, which may include {@link Status#WAITING} if
* the timeout expires before the operation completes.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return the outcome
* @throws InterruptedException if execution was interrupted while waiting
*/
Status await(long timeout, TimeUnit unit) throws InterruptedException;

/**
* Waits (uninterruptibly) if necessary for the computation to complete, and then retrieves the result.
*
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an exception
*/
T getUninterruptibly() throws CancellationException, ExecutionException;

/**
* Waits (uninterruptibly) if necessary for at most the given time for the computation to complete, and then
* retrieves the result, if available.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an exception
* @throws TimeoutException if the wait timed out
*/
T getUninterruptibly(long timeout, TimeUnit unit) throws CancellationException, ExecutionException, TimeoutException;

/**
* Wait (uninterruptibly) if necessary for this operation to complete, returning the outcome. The outcome will be one of
* {@link Status#COMPLETE}, {@link Status#CANCELLED}, or {@link Status#FAILED}.
*
* @return the outcome
*/
Status awaitUninterruptibly();

/**
* Wait if necessary for this operation to complete, returning the outcome, which may include {@link Status#WAITING} if
* the timeout expires before the operation completes.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return the outcome
*/
Status awaitUninterruptibly(long timeout, TimeUnit unit);

/**
* Get (poll) the current status of the asynchronous operation.
*
* @return the current status
*/
Status getStatus();

/**
* Add an asynchronous listener to be called when this operation completes.
*
* @param listener the listener to add
* @param attachment the attachment to pass in
* @param <A> the attachment type
*/
<A> void addListener(Listener<? super T, A> listener, A attachment);

/**
* Synchronously cancel a task, blocking uninterruptibly until it is known whether such cancellation was
* successful. Note that the {@link Future#cancel(boolean)} is somewhat unclear about blocking semantics.
* It is recommended to use {@link #asyncCancel(boolean)} instead.
*
* @param interruptionDesired if interruption is desired (if available)
* @return {@code true} if cancel succeeded, {@code false} otherwise
*/
boolean cancel(boolean interruptionDesired);

/** {@inheritDoc} */
void asyncCancel(boolean interruptionDesired);

/**
* The possible statuses of an {@link AsyncFuture}.
*/
enum Status {

/**
* The operation is still in progress.
*/
WAITING,
/**
* The operation has completed successfully.
*/
COMPLETE,
/**
* The operation was cancelled before it completed.
*/
CANCELLED,
/**
* The operation has failed with some exception.
*/
FAILED,
;
}

/**
* A listener for an asynchronous future computation result. Each listener method is passed the
* {@link AsyncFuture} which it was added to, as well as the {@code attachment} which was passed in to
* {@link AsyncFuture#addListener(Listener, Object)}.
*
* @param <T> the future type
* @param <A> the attachment type
*/
interface Listener<T, A> extends java.util.EventListener {

/**
* Handle a successful computation result.
*
* @param future the future
* @param attachment the attachment
*/
void handleComplete(AsyncFuture<? extends T> future, A attachment);

/**
* Handle a failure result.
*
* @param future the future
* @param cause the reason for the failure
* @param attachment the attachment
*/
void handleFailed(AsyncFuture<? extends T> future, Throwable cause, A attachment);

/**
* Handle a cancellation result.
*
* @param future the future
* @param attachment the attachment
*/
void handleCancelled(AsyncFuture<? extends T> future, A attachment);
}

/**
* An abstract base class for an implementation of the {@code Listener} interface. The implementation
* methods do nothing unless overridden.
*
* @param <T> the future type
* @param <A> the attachment type
*/
abstract class AbstractListener<T, A> implements Listener<T, A> {

/** {@inheritDoc} */
public void handleComplete(final AsyncFuture<? extends T> future, final A attachment) {
}

/** {@inheritDoc} */
public void handleFailed(final AsyncFuture<? extends T> future, final Throwable cause, final A attachment) {
}

/** {@inheritDoc} */
public void handleCancelled(final AsyncFuture<? extends T> future, final A attachment) {
}
}
}

0 comments on commit df7e3b9

Please sign in to comment.