package org.bukkit.craftbukkit.scheduler;
import org.bukkit.plugin.Plugin;
import java.util.concurrent.Callable;
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;
class CraftFuture<T> extends CraftTask implements Future<T>
{
private final Callable<T> callable;
private T value;
private Exception exception = null;
CraftFuture(final Callable<T> callable, final Plugin plugin, final int id)
{
super(plugin, null, id, -1l);
this.callable = callable;
}
public synchronized boolean cancel(final boolean mayInterruptIfRunning)
{
if(getPeriod() != -1l)
{
return false;
}
setPeriod(-2l);
return true;
}
public boolean isCancelled()
{
return getPeriod() == -2l;
}
public boolean isDone()
{
final long period = this.getPeriod();
return period != -1l && period != -3l;
}
public T get() throws CancellationException, InterruptedException, ExecutionException
{
try
{
return get(0, TimeUnit.MILLISECONDS);
} catch(final TimeoutException e)
{
throw new Error(e);
}
}
public synchronized T get(long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
{
timeout = unit.toMillis(timeout);
long period = this.getPeriod();
long timestamp = timeout > 0 ? System.currentTimeMillis() : 0l;
while(true)
{
if(period == -1l || period == -3l)
{
this.wait(timeout);
period = this.getPeriod();
if(period == -1l || period == -3l)
{
if(timeout == 0l)
{
continue;
}
timeout += timestamp - (timestamp = System.currentTimeMillis());
if(timeout > 0)
{
continue;
}
throw new TimeoutException();
}
}
if(period == -2l)
{
throw new CancellationException();
}
if(period == -4l)
{
if(exception == null)
{
return value;
}
throw new ExecutionException(exception);
}
throw new IllegalStateException("Expected " + -1l + " to " + -4l + ", got " + period);
}
}
@Override
public void run()
{
synchronized(this)
{
if(getPeriod() == -2l)
{
return;
}
setPeriod(-3l);
}
try
{
value = callable.call();
} catch(final Exception e)
{
exception = e;
} finally
{
synchronized(this)
{
setPeriod(-4l);
this.notifyAll();
}
}
}
synchronized boolean cancel0()
{
if(getPeriod() != -1l)
{
return false;
}
setPeriod(-2l);
notifyAll();
return true;
}
}