play.libs.F Maven / Gradle / Ivy
package play.libs;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;
import play.exceptions.UnexpectedException;
public class F {
public static class Promise implements Future, F.Action {
final CountDownLatch taskLock = new CountDownLatch(1);
boolean cancelled = false;
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
public boolean isCancelled() {
return false;
}
public boolean isDone() {
return invoked;
}
public V getOrNull() {
return result;
}
public V get() throws InterruptedException, ExecutionException {
taskLock.await();
if (exception != null) {
// The result of the promise is an exception - throw it
throw new ExecutionException(exception);
}
return result;
}
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
taskLock.await(timeout, unit);
if (exception != null) {
// The result of the promise is an exception - throw it
throw new ExecutionException(exception);
}
return result;
}
List>> callbacks = new ArrayList>>();
boolean invoked = false;
V result = null;
Throwable exception = null;
public void invoke(V result) {
invokeWithResultOrException(result, null);
}
public void invokeWithException(Throwable t) {
invokeWithResultOrException(null, t);
}
protected void invokeWithResultOrException(V result, Throwable t) {
synchronized (this) {
if (!invoked) {
invoked = true;
this.result = result;
this.exception = t;
taskLock.countDown();
} else {
return;
}
}
for (F.Action> callback : callbacks) {
callback.invoke(this);
}
}
public void onRedeem(F.Action> callback) {
synchronized (this) {
if (!invoked) {
callbacks.add(callback);
}
}
if (invoked) {
callback.invoke(this);
}
}
public static Promise> waitAll(final Promise... promises) {
return waitAll(Arrays.asList(promises));
}
public static Promise> waitAll(final Collection> promises) {
final CountDownLatch waitAllLock = new CountDownLatch(promises.size());
final Promise> result = new Promise>() {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean r = true;
for (Promise f : promises) {
r = r & f.cancel(mayInterruptIfRunning);
}
return r;
}
@Override
public boolean isCancelled() {
boolean r = true;
for (Promise f : promises) {
r = r & f.isCancelled();
}
return r;
}
@Override
public boolean isDone() {
boolean r = true;
for (Promise f : promises) {
r = r & f.isDone();
}
return r;
}
@Override
public List get() throws InterruptedException, ExecutionException {
waitAllLock.await();
List r = new ArrayList();
for (Promise f : promises) {
r.add(f.get());
}
return r;
}
@Override
public List get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
waitAllLock.await(timeout, unit);
return get();
}
};
final F.Action> action = new F.Action>() {
public void invoke(Promise completed) {
waitAllLock.countDown();
if (waitAllLock.getCount() == 0) {
try {
result.invoke(result.get());
} catch (Exception e) {
result.invokeWithException(e);
}
}
}
};
for (Promise f : promises) {
f.onRedeem(action);
}
if(promises.isEmpty()) {
result.invoke(Collections.emptyList());
}
return result;
}
public static Promise> wait2(Promise tA, Promise tB) {
final Promise> result = new Promise>();
final Promise> t = waitAll(new Promise[]{tA, tB});
t.onRedeem(new F.Action>>() {
public void invoke(Promise> completed) {
List