| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * 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 com.intellij.util.concurrency; |
| |
| import com.intellij.openapi.util.Pair; |
| import org.jetbrains.annotations.NotNull; |
| 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 Pair<Object, Boolean> myValue; |
| |
| public synchronized void set(@Nullable T result) { |
| assertNotSet(); |
| |
| myValue = Pair.create((Object)result, true); |
| mySema.release(); |
| } |
| |
| public synchronized void setException(@NotNull Throwable e) { |
| assertNotSet(); |
| |
| myValue = Pair.create((Object)e, false); |
| mySema.release(); |
| } |
| |
| public synchronized void reset() { |
| try { |
| // wait till readers get their results |
| if (isDone()) mySema.acquire(); |
| } |
| catch (InterruptedException ignore) { |
| return; |
| } |
| myValue = null; |
| } |
| |
| private void assertNotSet() { |
| if (isDone()) throw new IllegalStateException("Result is already set"); |
| } |
| |
| @Override |
| public boolean cancel(boolean mayInterruptIfRunning) { |
| return false; |
| } |
| |
| @Override |
| public boolean isCancelled() { |
| return false; |
| } |
| |
| @Override |
| public boolean isDone() { |
| return myValue != null; |
| } |
| |
| @Override |
| public T get() throws InterruptedException, ExecutionException { |
| mySema.acquire(); |
| try { |
| return doGet(); |
| } |
| finally { |
| mySema.release(); |
| } |
| } |
| |
| @Override |
| public T get(long timeout, @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { |
| if (!mySema.tryAcquire(timeout, unit)) throw new TimeoutException(); |
| try { |
| return doGet(); |
| } |
| finally { |
| mySema.release(); |
| } |
| } |
| |
| @Nullable |
| public T tryGet() throws ExecutionException { |
| return doGet(); |
| } |
| |
| @Nullable |
| private T doGet() throws ExecutionException { |
| Pair<Object, Boolean> pair = myValue; |
| if (pair == null) return null; |
| |
| if (!pair.second) throw new ExecutionException(((Throwable)pair.first).getMessage(), (Throwable)pair.first); |
| //noinspection unchecked |
| return (T)pair.first; |
| } |
| } |