/**********************************************************\
| |
| hprose |
| |
| Official WebSite: http://www.hprose.com/ |
| http://www.hprose.org/ |
| |
\**********************************************************/
/**********************************************************\
* *
* Promise.java *
* *
* Promise class for Java. *
* *
* LastModified: Sep 19, 2016 *
* Author: Ma Bingyao <andot@hprose.com> *
* *
\**********************************************************/
package hprose.util.concurrent;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public final class Promise<V> implements Resolver<V>, Rejector, Thenable<V> {
private static volatile ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
static {
Threads.registerShutdownHandler(new Runnable() {
public void run() {
ScheduledExecutorService t = timer;
timer = Executors.newSingleThreadScheduledExecutor();
t.shutdownNow();
}
});
}
private final LinkedList<Subscriber<?, V>> subscribers = new LinkedList<Subscriber<?, V>>();
private volatile AtomicReference<State> state = new AtomicReference<State>(State.PENDING);
private volatile V value;
private volatile Throwable reason;
public Promise() {}
public Promise(final Call<V> computation) {
timer.execute(new Runnable() {
public void run() {
try {
Promise.this.resolve(computation.call());
}
catch (Throwable e) {
Promise.this.reject(e);
}
}
});
}
public Promise(final AsyncCall<V> computation) {
timer.execute(new Runnable() {
public void run() {
try {
Promise.this.resolve(computation.call());
}
catch (Throwable e) {
Promise.this.reject(e);
}
}
});
}
public Promise(Executor<V> executor) {
executor.exec((Resolver<V>)this, (Rejector)this);
}
public final static <T> Promise<T> value(T value) {
Promise<T> promise = new Promise<T>();
promise.resolve(value);
return promise;
}
public final static <T> Promise<T> value(Promise<T> value) {
Promise<T> promise = new Promise<T>();
promise.resolve(value);
return promise;
}
public final static <T> Promise<T> value(Thenable<T> value) {
Promise<T> promise = new Promise<T>();
promise.resolve(value);
return promise;
}
public final static <T> Promise<T> error(Throwable reason) {
Promise<T> promise = new Promise<T>();
promise.reject(reason);
return promise;
}
public final static <T> Promise<T> delayed(long duration, TimeUnit timeunit, final Call<T> computation) {
final Promise<T> promise = new Promise<T>();
timer.schedule(new Runnable() {
public void run() {
try {
promise.resolve(computation.call());
}
catch (Throwable e) {
promise.reject(e);
}
}
}, duration, timeunit);
return promise;
}
public final static <T> Promise<T> delayed(long duration, TimeUnit timeunit, final AsyncCall<T> computation) {
final Promise<T> promise = new Promise<T>();
timer.schedule(new Runnable() {
public void run() {
try {
promise.resolve(computation.call());
}
catch (Throwable e) {
promise.reject(e);
}
}
}, duration, timeunit);
return promise;
}
public final static <T> Promise<T> delayed(long duration, TimeUnit timeunit, final T value) {
final Promise<T> promise = new Promise<T>();
timer.schedule(new Runnable() {
public void run() {
promise.resolve(value);
}
}, duration, timeunit);
return promise;
}
public final static <T> Promise<T> delayed(long duration, TimeUnit timeunit, final Promise<T> value) {
final Promise<T> promise = new Promise<T>();
timer.schedule(new Runnable() {
public void run() {
promise.resolve(value);
}
}, duration, timeunit);
return promise;
}
public final static <T> Promise<T> delayed(long duration, Call<T> computation) {
return delayed(duration, TimeUnit.MILLISECONDS, computation);
}
public final static <T> Promise<T> delayed(long duration, AsyncCall<T> computation) {
return delayed(duration, TimeUnit.MILLISECONDS, computation);
}
public final static <T> Promise<T> delayed(long duration, T value) {
return delayed(duration, TimeUnit.MILLISECONDS, value);
}
public final static <T> Promise<T> delayed(long duration, Promise<T> value) {
return delayed(duration, TimeUnit.MILLISECONDS, value);
}
public final static <T> Promise<T> sync(Call<T> computation) {
try {
return value(computation.call());
}
catch (Throwable e) {
return error(e);
}
}
public final static <T> Promise<T> sync(AsyncCall<T> computation) {
try {
return value(computation.call());
}
catch (Throwable e) {
return error(e);
}
}
public final static boolean isThenable(Object value) {
return value instanceof Thenable;
}
public final static boolean isPromise(Object value) {
return value instanceof Promise;
}
public final static Promise<?> toPromise(Object value) {
return isPromise(value) ? (Promise<?>)value : value(value);
}
@SuppressWarnings("unchecked")
private static <T> void allHandler(final Promise<T[]> promise, final AtomicInteger count, final T[] result, Object element, final int i) {
((Promise<T>)toPromise(element)).then(
new Action<T>() {
public void call(T value) throws Throwable {
result[i] = value;
if (count.decrementAndGet() == 0) {
promise.resolve(result);
}
}
},
new Action<Throwable>() {
public void call(Throwable e) throws Throwable {
promise.reject(e);
}
}
);
}
@SuppressWarnings("unchecked")
public final static <T> Promise<T[]> all(Object[] array, Class<T> type) {
if (array == null) return value((T[])null);
int n = array.length;
T[] result = (type == Object.class) ?
(T[])(new Object[n]) :
(T[])Array.newInstance(type, n);
if (n == 0) return value(result);
AtomicInteger count = new AtomicInteger(n);
Promise<T[]> promise = new Promise<T[]>();
for (int i = 0; i < n; ++i) {
allHandler(promise, count, result, array[i], i);
}
return promise;
}
public final static Promise<Object[]> all(Object[] array) {
return all(array, Object.class);
}
public final static <T> Promise<T[]> all(Promise<Object[]> promise, final Class<T> type) {
return promise.then(new AsyncFunc<T[], Object[]>() {
public Promise<T[]> call(Object[] array) throws Throwable {
return all(array, type);
}
});
}
public final static Promise<Object[]> all(Promise<Object[]> promise) {
return all(promise, Object.class);
}
@SuppressWarnings("unchecked")
public final <T> Promise<T[]> all(Class<T> type) {
return all((Promise<Object[]>)this, type);
}
@SuppressWarnings("unchecked")
public final Promise<Object[]> all() {
return all((Promise<Object[]>)this);
}
public final static Promise<Object[]> join(Object...args) {
return all(args);
}
@SuppressWarnings("unchecked")
public final static <T> Promise<T> race(Object[] array, Class<T> type) {
Promise<T> promise = new Promise<T>();
for (int i = 0, n = array.length; i < n; ++i) {
((Promise<T>)toPromise(array[i])).fill(promise);
}
return promise;
}
public final static Promise<?> race(Object[] array) {
return race(array, Object.class);
}
public final static <T> Promise<T> race(Promise<Object[]> promise, final Class<T> type) {
return promise.then(new AsyncFunc<T, Object[]>() {
public Promise<T> call(Object[] array) throws Throwable {
return race(array, type);
}
});
}
public final static Promise<?> race(Promise<Object[]> promise) {
return race(promise, Object.class);
}
@SuppressWarnings("unchecked")
public final <T> Promise<T> race(Class<T> type) {
return race((Promise<Object[]>)this, type);
}
@SuppressWarnings("unchecked")
public final Promise<?> race() {
return race((Promise<Object[]>)this);
}
@SuppressWarnings("unchecked")
public final static <T> Promise<T> any(Object[] array, Class<T> type) {
int n = array.length;
if (n == 0) {
return (Promise<T>)Promise.error(new IllegalArgumentException("any(): array must not be empty"));
}
final RuntimeException reason = new RuntimeException("any(): all promises failed");
final Promise<T> promise = new Promise<T>();
final AtomicInteger count = new AtomicInteger(n);
for (int i = 0; i < n; ++i) {
((Promise<T>)toPromise(array[i])).then(
new Action<T>() {
public void call(T value) throws Throwable {
promise.resolve(value);
}
},
new Action<Throwable>() {
public void call(Throwable e) throws Throwable {
if (count.decrementAndGet() == 0) {
promise.reject(reason);
}
}
}
);
}
return promise;
}
public final static Promise<?> any(Object[] array) {
return any(array, Object.class);
}
public final static <T> Promise<T> any(Promise<Object[]> promise, final Class<T> type) {
return promise.then(new AsyncFunc<T, Object[]>() {
public Promise<T> call(Object[] array) throws Throwable {
return any(array, type);
}
});
}
public final static Promise<?> any(Promise<Object[]> promise) {
return any(promise, Object.class);
}
@SuppressWarnings("unchecked")
public final <T> Promise<T> any(Class<T> type) {
return any((Promise<Object[]>)this, type);
}
@SuppressWarnings("unchecked")
public final Promise<?> any() {
return any((Promise<Object[]>)this);
}
public final static Promise<?> run(Action<Object[]> handler, Object...args) {
return all(args).then(handler);
}
public final static <V> Promise<V> run(Func<V, Object[]> handler, Object...args) {
return all(args).then(handler);
}
public final static <V> Promise<V> run(AsyncFunc<V, Object[]> handler, Object...args) {
return all(args).then(handler);
}
public final static <T> Promise<?> run(Class<T> type, Action<T[]> handler, Object...args) {
return all(args, type).then(handler);
}
public final static <V, T> Promise<V> run(Class<T> type, Func<V, T[]> handler, Object...args) {
return all(args, type).then(handler);
}
public final static <V, T> Promise<V> run(Class<T> type, AsyncFunc<V, T[]> handler, Object...args) {
return all(args, type).then(handler);
}
@SuppressWarnings("unchecked")
public final static <V> Promise<?> forEach(final Action<V> callback, Object...args) {
return all(args).then(new Action<Object[]>() {
public void call(Object[] array) throws Throwable {
if (array == null) return;
for (int i = 0, n = array.length; i < n; ++i) {
callback.call((V)array[i]);
}
}
});
}
@SuppressWarnings("unchecked")
private static <V> Action<Object[]> getForEachHandler(final Handler<?, V> callback) {
return new Action<Object[]>() {
public void call(Object[] array) throws Throwable {
if (array == null) return;
for (int i = 0, n = array.length; i < n; ++i) {
callback.call((V)array[i], i);
}
}
};
}
public final static <V> Promise<?> forEach(Object[] array, Handler<?, V> callback) {
return all(array).then(getForEachHandler(callback));
}
public final static <V> Promise<?> forEach(Promise<Object[]> array, Handler<?, V> callback) {
return all(array).then(getForEachHandler(callback));
}
public final Promise<?> forEach(Handler<?, V> callback) {
return this.all().then(getForEachHandler(callback));
}
@SuppressWarnings("unchecked")
public final static <V> Promise<Boolean> every(final Func<Boolean, V> callback, Object...args) {
return all(args).then(new Func<Boolean, Object[]>() {
public Boolean call(Object[] array) throws Throwable {
for (int i = 0, n = array.length; i < n; ++i) {
if (!callback.call((V)array[i])) return false;
}
return true;
}
});
}
@SuppressWarnings("unchecked")
private static <V> Func<Boolean, Object[]> getEveryHandler(final Handler<Boolean, V> callback) {
return new Func<Boolean, Object[]>() {
public Boolean call(Object[] array) throws Throwable {
for (int i = 0, n = array.length; i < n; ++i) {
if (!callback.call((V)array[i], i)) return false;
}
return true;
}
};
}
public final static <V> Promise<Boolean> every(Object[] array, Handler<Boolean, V> callback) {
return all(array).then(getEveryHandler(callback));
}
public final static <V> Promise<Boolean> every(Promise<Object[]> array, Handler<Boolean, V> callback) {
return all(array).then(getEveryHandler(callback));
}
public final <V> Promise<Boolean> every(Handler<Boolean, V> callback) {
return all().then(getEveryHandler(callback));
}
@SuppressWarnings("unchecked")
public final static <V> Promise<Boolean> some(final Func<Boolean, V> callback, Object...args) {
return all(args).then(new Func<Boolean, Object[]>() {
public Boolean call(Object[] array) throws Throwable {
if (array == null) return false;
for (int i = 0, n = array.length; i < n; ++i) {
if (callback.call((V)array[i])) return true;
}
return false;
}
});
}
@SuppressWarnings("unchecked")
private static <V> Func<Boolean, Object[]> getSomeHandler(final Handler<Boolean, V> callback) {
return new Func<Boolean, Object[]>() {
public Boolean call(Object[] array) throws Throwable {
if (array == null) return false;
for (int i = 0, n = array.length; i < n; ++i) {
if (callback.call((V)array[i], i)) return true;
}
return false;
}
};
}
public final static <V> Promise<Boolean> some(Object[] array, Handler<Boolean, V> callback) {
return all(array).then(getSomeHandler(callback));
}
public final static <V> Promise<Boolean> some(Promise<Object[]> array, Handler<Boolean, V> callback) {
return all(array).then(getSomeHandler(callback));
}
public final <V> Promise<Boolean> some(Handler<Boolean, V> callback) {
return this.all().then(getSomeHandler(callback));
}
@SuppressWarnings("unchecked")
public final static <V> Promise<Object[]> filter(final Func<Boolean, V> callback, Object...args) {
return all(args).then(new Func<Object[], Object[]>() {
public Object[] call(Object[] array) throws Throwable {
if (array == null) return null;
int n = array.length;
ArrayList<Object> result = new ArrayList<Object>(n);
for (int i = 0; i < n; ++i) {
if (callback.call((V)array[i])) result.add(array[i]);
}
return result.toArray();
}
});
}
@SuppressWarnings("unchecked")
private static <V, T> Func<T[], T[]> getFilterHandler(final Handler<Boolean, V> callback, final Class<T> type) {
return new Func<T[], T[]>() {
public T[] call(T[] array) throws Throwable {
if (array == null) return null;
int n = array.length;
ArrayList<T> result = new ArrayList<T>(n);
for (int i = 0; i < n; ++i) {
if (callback.call((V)array[i], i)) result.add(array[i]);
}
return result.toArray((type == Object.class) ?
(T[])(new Object[result.size()]) :
(T[])Array.newInstance(type, result.size()));
}
};
}
public final static <V, T> Promise<T[]> filter(Object[] array, Handler<Boolean, V> callback, Class<T> type) {
return all(array, type).then(getFilterHandler(callback, type));
}
public final static <V> Promise<Object[]> filter(Object[] array, Handler<Boolean, V> callback) {
return filter(array, callback, Object.class);
}
public final static <V, T> Promise<T[]> filter(Promise<Object[]> array, Handler<Boolean, V> callback, Class<T> type) {
return all(array, type).then(getFilterHandler(callback, type));
}
public final static <V> Promise<Object[]> filter(Promise<Object[]> array, Handler<Boolean, V> callback) {
return filter(array, callback, Object.class);
}
public final <V, T> Promise<T[]> filter(Handler<Boolean, V> callback, Class<T> type) {
return all(type).then(getFilterHandler(callback, type));
}
public final <V> Promise<Object[]> filter(Handler<Boolean, V> callback) {
return filter(callback, Object.class);
}
@SuppressWarnings("unchecked")
public final static <V> Promise<Object[]> map(final Func<?, V> callback, Object...args) {
return all(args).then(new Func<Object[], Object[]>() {
public Object[] call(Object[] array) throws Throwable {
if (array == null) return null;
int n = array.length;
Object[] result = new Object[n];
for (int i = 0; i < n; ++i) {
result[i] = callback.call((V)array[i]);
}
return result;
}
});
}
@SuppressWarnings("unchecked")
private static <V, T> Func<T[], Object[]> getMapHandler(final Handler<T, V> callback, final Class<T> type) {
return new Func<T[], Object[]>() {
public T[] call(Object[] array) throws Throwable {
if (array == null) return null;
int n = array.length;
T[] result = (type == Object.class) ?
(T[])(new Object[n]) :
(T[])Array.newInstance(type, n);
for (int i = 0; i < n; ++i) {
result[i] = callback.call((V)array[i], i);
}
return result;
}
};
}
@SuppressWarnings("unchecked")
private static <V> Func<Object[], Object[]> getMapHandler(final Handler<?, V> callback) {
return new Func<Object[], Object[]>() {
public Object[] call(Object[] array) throws Throwable {
if (array == null) return null;
int n = array.length;
Object[] result = new Object[n];
for (int i = 0; i < n; ++i) {
result[i] = callback.call((V)array[i], i);
}
return result;
}
};
}
public final static <V, T> Promise<T[]> map(Object[] array, Handler<T, V> callback, Class<T> type) {
return all(array).then(getMapHandler(callback, type));
}
public final static <V> Promise<Object[]> map(Object[] array, Handler<?, V> callback) {
return all(array).then(getMapHandler(callback));
}
public final static <V, T> Promise<T[]> map(Promise<Object[]> array, Handler<T, V> callback, Class<T> type) {
return all(array).then(getMapHandler(callback, type));
}
public final static <V> Promise<Object[]> map(Promise<Object[]> array, Handler<?, V> callback) {
return all(array).then(getMapHandler(callback));
}
public final <V, T> Promise<T[]> map(Handler<T, V> callback, Class<T> type) {
return all().then(getMapHandler(callback, type));
}
public final <V> Promise<Object[]> map(Handler<?, V> callback) {
return all().then(getMapHandler(callback));
}
@SuppressWarnings("unchecked")
private static <V> Func<V, Object[]> getReduceHandler(final Reducer<V, V> callback) {
return new Func<V, Object[]>() {
public V call(Object[] array) throws Throwable {
if (array == null) return null;
int n = array.length;
if (n == 0) return null;
V result = (V)array[0];
for (int i = 1; i < n; ++i) {
result = callback.call(result, (V)array[i], i);
}
return result;
}
};
}
public final static <V> Promise<V> reduce(Object[] array, Reducer<V, V> callback) {
return all(array).then(getReduceHandler(callback));
}
public final static <V> Promise<V> reduce(Promise<Object[]> array, Reducer<V, V> callback) {
return all(array).then(getReduceHandler(callback));
}
public final <V> Promise<V> reduce(Reducer<V, V> callback) {
return all().then(getReduceHandler(callback));
}
@SuppressWarnings("unchecked")
private static <R, V> Func<R, Object[]> getReduceHandler(final Reducer<R, V> callback, final R initialValue) {
return new Func<R, Object[]>() {
public R call(Object[] array) throws Throwable {
if (array == null) return initialValue;
int n = array.length;
if (n == 0) return initialValue;
R result = initialValue;
for (int i = 0; i < n; ++i) {
result = callback.call(result, (V)array[i], i);
}
return result;
}
};
}
public final static <R, V> Promise<R> reduce(Object[] array, Reducer<R, V> callback, R initialValue) {
return all(array).then(getReduceHandler(callback, initialValue));
}
public final static <R, V> Promise<R> reduce(Promise<Object[]> array, Reducer<R, V> callback, R initialValue) {
return all(array).then(getReduceHandler(callback, initialValue));
}
public final <R, V> Promise<R> reduce(Reducer<R, V> callback, R initialValue) {
return all().then(getReduceHandler(callback, initialValue));
}
@SuppressWarnings("unchecked")
private static <V> Func<V, Object[]> getReduceRightHandler(final Reducer<V, V> callback) {
return new Func<V, Object[]>() {
public V call(Object[] array) throws Throwable {
if (array == null) return null;
int n = array.length;
if (n == 0) return null;
V result = (V)array[n - 1];
for (int i = n - 2; i >= 0; --i) {
result = callback.call(result, (V)array[i], i);
}
return result;
}
};
}
public final static <V> Promise<V> reduceRight(Object[] array, Reducer<V, V> callback) {
return all(array).then(getReduceRightHandler(callback));
}
public final static <V> Promise<V> reduceRight(Promise<Object[]> array, Reducer<V, V> callback) {
return all(array).then(getReduceRightHandler(callback));
}
public final <V> Promise<V> reduceRight(Reducer<V, V> callback) {
return all().then(getReduceRightHandler(callback));
}
@SuppressWarnings("unchecked")
private static <R, V> Func<R, Object[]> getReduceRightHandler(final Reducer<R, V> callback, final R initialValue) {
return new Func<R, Object[]>() {
public R call(Object[] array) throws Throwable {
if (array == null) return initialValue;
int n = array.length;
if (n == 0) return initialValue;
R result = initialValue;
for (int i = n - 1; i >= 0; --i) {
result = callback.call(result, (V)array[i], i);
}
return result;
}
};
}
public final static <R, V> Promise<R> reduceRight(Object[] array, Reducer<R, V> callback, R initialValue) {
return all(array).then(getReduceRightHandler(callback, initialValue));
}
public final static <R, V> Promise<R> reduceRight(Promise<Object[]> array, Reducer<R, V> callback, R initialValue) {
return all(array).then(getReduceRightHandler(callback, initialValue));
}
public final <R, V> Promise<R> reduceRight(Reducer<R, V> callback, R initialValue) {
return all().then(getReduceRightHandler(callback, initialValue));
}
@SuppressWarnings("unchecked")
private <R, V> void call(final Callback<R, V> callback, final Promise<R> next, final V x) {
try {
if (callback instanceof Action) {
((Action<V>)callback).call(x);
next.resolve((R)null);
}
else if (callback instanceof Func) {
next.resolve((R)((Func<R, V>)callback).call(x));
}
else if (callback instanceof AsyncFunc) {
next.resolve((Promise<R>)((AsyncFunc<R, V>)callback).call(x));
}
}
catch (Throwable e) {
next.reject(e);
}
}
@SuppressWarnings("unchecked")
private <R, V> void resolve(final Callback<R, V> onfulfill, final Promise<R> next, final V x) {
if (onfulfill != null) {
call(onfulfill, next, x);
}
else {
next.resolve((R)x);
}
}
private <R> void reject(final Callback<R, Throwable> onreject, final Promise<R> next, final Throwable e) {
if (onreject != null) {
call(onreject, next, e);
}
else {
next.reject(e);
}
}
@SuppressWarnings("unchecked")
private synchronized <R> void _resolve(V value) {
if (state.compareAndSet(State.PENDING, State.FULFILLED)) {
this.value = value;
while (!subscribers.isEmpty()) {
Subscriber<R, V> subscriber = (Subscriber<R, V>)subscribers.poll();
resolve(subscriber.onfulfill, subscriber.next, value);
}
}
}
@SuppressWarnings("unchecked")
public final void resolve(Object value) {
if (isPromise(value)) {
resolve((Promise<V>)value);
}
else if (isThenable(value)) {
resolve((Thenable<V>)value);
}
else {
_resolve((V)value);
}
}
public final void resolve(Thenable<V> value) {
final AtomicBoolean notrun = new AtomicBoolean(true);
Action<V> resolveFunction = new Action<V>() {
public void call(V y) throws Throwable {
if (notrun.compareAndSet(true, false)) {
resolve(y);
}
}
};
Action<Throwable> rejectFunction = new Action<Throwable>() {
public void call(Throwable e) throws Throwable {
if (notrun.compareAndSet(true, false)) {
reject(e);
}
}
};
try {
value.then(resolveFunction, rejectFunction);
}
catch (Throwable e) {
if (notrun.compareAndSet(true, false)) {
reject(e);
}
}
}
public final void resolve(Promise<V> value) {
if (value == null) {
_resolve(null);
}
else if (value == this) {
reject(new TypeException("Self resolution"));
}
else {
value.fill(this);
}
}
@SuppressWarnings("unchecked")
private synchronized <R> void _reject(Throwable e) {
if (state.compareAndSet(State.PENDING, State.REJECTED)) {
this.reason = e;
while (!subscribers.isEmpty()) {
Subscriber<R, V> subscriber = (Subscriber<R, V>)subscribers.poll();
reject(subscriber.onreject, subscriber.next, e);
}
}
}
public final void reject(Throwable e) {
_reject(e);
}
public final Promise<?> then(Action<V> onfulfill) {
return then(onfulfill, null);
}
public final <R> Promise<R> then(Func<R, V> onfulfill) {
return then((Callback<R, V>)onfulfill, null);
}
public final <R> Promise<R> then(AsyncFunc<R, V> onfulfill) {
return then((Callback<R, V>)onfulfill, null);
}
public final Promise<?> then(Action<V> onfulfill, Action<Throwable> onreject) {
return then((Callback<Void, V>)onfulfill, (Callback<Void, Throwable>)onreject);
}
public final <R> Promise<R> then(Func<R, V> onfulfill, Func<R, Throwable> onreject) {
return then((Callback<R, V>)onfulfill, (Callback<R, Throwable>)onreject);
}
public final <R> Promise<R> then(AsyncFunc<R, V> onfulfill, Func<R, Throwable> onreject) {
return then((Callback<R, V>)onfulfill, (Callback<R, Throwable>)onreject);
}
public final <R> Promise<R> then(AsyncFunc<R, V> onfulfill, AsyncFunc<R, Throwable> onreject) {
return then((Callback<R, V>)onfulfill, (Callback<R, Throwable>)onreject);
}
public final <R> Promise<R> then(Func<R, V> onfulfill, AsyncFunc<R, Throwable> onreject) {
return then((Callback<R, V>)onfulfill, (Callback<R, Throwable>)onreject);
}
@SuppressWarnings("unchecked")
private synchronized <R> Promise<R> then(Callback<R, V> onfulfill, Callback<R, Throwable> onreject) {
Promise<R> next = new Promise<R>();
switch (state.get()) {
case FULFILLED:
resolve(onfulfill, next, value);
break;
case REJECTED:
reject(onreject, next, reason);
break;
default:
subscribers.offer(new Subscriber<R, V>(onfulfill, onreject, next));
break;
}
return next;
}
public final void done(Action<V> onfulfill) {
done(onfulfill, null);
}
public final void done(Action<V> onfulfill, Action<Throwable> onreject) {
then(onfulfill, onreject).then(null, new Action<Throwable>() {
public void call(final Throwable e) {
timer.execute(new Runnable() {
public void run() {
throw new RuntimeException(e);
}
});
}
});
}
public final State getState() {
return state.get();
}
public final V getValue() {
return value;
}
public final Throwable getReason() {
return reason;
}
public final Promise<?> catchError(Action<Throwable> onreject) {
return then(null, onreject);
}
public final <R> Promise<R> catchError(Func<R, Throwable> onreject) {
return then((Callback<R, V>)null, onreject);
}
public final <R> Promise<R> catchError(AsyncFunc<R, Throwable> onreject) {
return then((Callback<R, V>)null, onreject);
}
public final Promise<?> catchError(Action<Throwable> onreject, Func<Boolean, Throwable> test) {
return catchError((Callback<Void, Throwable>)onreject, test);
}
public final <R> Promise<R> catchError(Func<R, Throwable> onreject, Func<Boolean, Throwable> test) {
return catchError((Callback<R, Throwable>)onreject, test);
}
public final <R> Promise<R> catchError(AsyncFunc<R, Throwable> onreject, Func<Boolean, Throwable> test) {
return catchError((Callback<R, Throwable>)onreject, test);
}
public final Promise<?> catchError(Action<Throwable> onreject, AsyncFunc<Boolean, Throwable> test) {
return catchError((Callback<Void, Throwable>)onreject, test);
}
public final <R> Promise<R> catchError(Func<R, Throwable> onreject, AsyncFunc<Boolean, Throwable> test) {
return catchError((Callback<R, Throwable>)onreject, test);
}
public final <R> Promise<R> catchError(AsyncFunc<R, Throwable> onreject, AsyncFunc<Boolean, Throwable> test) {
return catchError((Callback<R, Throwable>)onreject, test);
}
@SuppressWarnings("unchecked")
private <R> Promise<R> catchError(final Callback<R, Throwable> onreject, final Func<Boolean, Throwable> test) {
if (test != null) {
return then((Callback<R, V>)null, new AsyncFunc<R, Throwable>() {
public Promise<R> call(Throwable e) throws Throwable {
if (test.call(e)) {
return then(null, onreject);
}
throw e;
}
});
}
return then(null, onreject);
}
@SuppressWarnings("unchecked")
private <R> Promise<R> catchError(final Callback<R, Throwable> onreject, final AsyncFunc<Boolean, Throwable> test) {
if (test != null) {
return then((Callback<R, V>)null, new AsyncFunc<R, Throwable>() {
public Promise<R> call(final Throwable e) throws Throwable {
return test.call(e).then(new AsyncFunc<R, Boolean>() {
public Promise<R> call(Boolean value) throws Throwable {
if (value) {
return then(null, onreject);
}
throw e;
}
});
}
});
}
return then(null, onreject);
}
public final void fail(Action<Throwable> onreject) {
done(null, onreject);
}
public final Promise<V> whenComplete(final Runnable action) {
return then(
new Func<V, V>() {
public V call(final V value) throws Throwable {
action.run();
return value;
}
},
new Func<V, Throwable>() {
public V call(final Throwable e) throws Throwable {
action.run();
throw e;
}
}
);
}
public final Promise<V> whenComplete(final Action<?> action) {
return then(
new Func<V, V>() {
@SuppressWarnings("unchecked")
public V call(final V value) throws Throwable {
((Action<V>)action).call(value);
return value;
}
},
new Func<V, Throwable>() {
@SuppressWarnings("unchecked")
public V call(final Throwable e) throws Throwable {
((Action<Throwable>)action).call(e);
throw e;
}
}
);
}
@SuppressWarnings("unchecked")
public final Promise<?> complete(Action<?> oncomplete) {
return then((Action<V>)oncomplete, (Action<Throwable>)oncomplete);
}
@SuppressWarnings("unchecked")
public final <R> Promise<R> complete(Func<R, ?> oncomplete) {
return then((Func<R, V>)oncomplete, (Func<R, Throwable>)oncomplete);
}
@SuppressWarnings("unchecked")
public final <R> Promise<R> complete(AsyncFunc<R, ?> oncomplete) {
return then((AsyncFunc<R, V>)oncomplete, (AsyncFunc<R, Throwable>)oncomplete);
}
@SuppressWarnings("unchecked")
public final void always(Action<?> oncomplete) {
done((Action<V>)oncomplete, (Action<Throwable>)oncomplete);
}
public final void fill(final Promise<V> promise) {
then(
new Action<V>() {
public void call(V value) throws Throwable {
promise.resolve(value);
}
},
new Action<Throwable>() {
public void call(Throwable e) throws Throwable {
promise.reject(e);
}
}
);
}
public final Promise<V> timeout(long duration, TimeUnit timeunit, final Throwable reason) {
final Promise<V> promise = new Promise<V>();
final Future<?> timeoutID = timer.schedule(new Runnable() {
public void run() {
if (reason == null) {
promise.reject(new TimeoutException("timeout"));
}
else {
promise.reject(reason);
}
}
}, duration, timeunit);
whenComplete(new Runnable() {
public void run() {
timeoutID.cancel(true);
}
}).fill(promise);
return promise;
}
public final Promise<V> timeout(long duration, Throwable reason) {
return timeout(duration, TimeUnit.MILLISECONDS, reason);
}
public final Promise<V> timeout(long duration) {
return timeout(duration, TimeUnit.MILLISECONDS, null);
}
public final Promise<V> delay(final long duration, final TimeUnit timeunit) {
final Promise<V> promise = new Promise<V>();
then(new Action<V>() {
public void call(final V value) throws Throwable {
timer.schedule(new Runnable() {
public void run() {
promise.resolve(value);
}
}, duration, timeunit);
}
},
new Action<Throwable>() {
public void call(Throwable e) throws Throwable {
promise.reject(e);
}
}
);
return promise;
}
public final Promise<V> delay(long duration) {
return delay(duration, TimeUnit.MILLISECONDS);
}
@SuppressWarnings("unchecked")
public final Promise<V> tap(final Action<V> onfulfilledSideEffect) {
return then(new Func<V, V>() {
public V call(V value) throws Throwable {
onfulfilledSideEffect.call(value);
return value;
}
});
}
public final Future<V> toFuture() {
return new PromiseFuture<V>(this);
}
}