package com.intellij.util.concurrency; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import org.jetbrains.annotations.Nullable; import java.util.concurrent.*; import java.util.concurrent.Semaphore; public class FutureResult<T> implements Future<T> { private final Semaphore mySema = new Semaphore(0); private volatile Ref<Pair<Object, Boolean>> myValue; public void reset() { mySema.drainPermits(); myValue = null; } public boolean cancel(boolean mayInterruptIfRunning) { return false; } public boolean isCancelled() { return false; } public boolean isDone() { return myValue != null; } public void set(@Nullable T result) { if (myValue != null) throw new IllegalStateException("Result is already set"); myValue = Ref.create(Pair.create((Object)result, true)); mySema.release(); } public void setException(Throwable e) { assert myValue == null; myValue = Ref.create(Pair.create((Object)e, false)); mySema.release(); } public T get() throws InterruptedException, ExecutionException { mySema.acquire(); try { return doGet(); } finally { mySema.release(); } } public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { if (!mySema.tryAcquire(timeout, unit)) throw new TimeoutException(); try { return doGet(); } finally { mySema.release(); } } private T doGet() throws ExecutionException { Pair<Object, Boolean> pair = myValue.get(); if (!pair.second) throw new ExecutionException(((Throwable)pair.first).getMessage(), (Throwable)pair.first); return (T)pair.first; } }