/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* --
*/
package com.sun.sgs.impl.nio;
import com.sun.sgs.nio.channels.IoFuture;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* An implementation of {@code IoFuture} that adds an object attachment to a
* {@code FutureTask}.
*
* @param <R> the result type
* @param <A> the attachment type
*/
public class IoFutureTask<R, A> extends FutureTask<R>
implements IoFuture<R, A>
{
/**
* The attachment for this {@code IoFuture}. This field is
* {@code volatile} to match the attachment implementation in
* {@link java.nio.channels.SelectionKey}.
*/
private volatile A attachment;
/**
* Creates an instance of this class for running the specified {@code
* Callable} and including the specified attachment.
*
* @param callable the callable task
* @param attachment the attachment; may be {@code null}
*/
public IoFutureTask(Callable<R> callable, A attachment) {
super(callable);
this.attachment = attachment;
}
/**
* Creates an instance of this class for running the specified {@code
* Callable} and including the specified attachment.
*
* @param <R> the result type
* @param <A> the attachment type
* @param callable the callable task
* @param attachment the attachment; may be {@code null}
* @return a new {@code IoFuture}
*/
public static <R, A> IoFuture newInstance(
Callable<R> callable, A attachment)
{
return new IoFutureTask<R, A>(callable, attachment);
}
/* -- Implement IoFuture -- */
/** {@inheritDoc} */
public R getNow() throws ExecutionException {
if (!isDone()) {
throw new IllegalStateException("The computation is not done");
}
/*
* The future is done, so a result should be available immediately.
* The following idiom appears in "Java Concurrency in Practice" to
* handle the case where this thread has been interrupted, but a result
* must be obtained regardless.
*/
boolean wasInterrupted = false;
try {
while (true) {
try {
return get();
} catch (InterruptedException e) {
wasInterrupted = true;
/* Fall through and retry */
}
}
} finally {
if (wasInterrupted) {
Thread.currentThread().interrupt();
}
}
}
/** {@inheritDoc} */
public A attachment() {
return attachment;
}
/** {@inheritDoc} */
public A attach(A newAttachment) {
A previousAttachment = attachment;
attachment = newAttachment;
return previousAttachment;
}
}