com.arangodb.shaded.vertx.core.impl.future.FutureImpl Maven / Gradle / Ivy
/*
* Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package com.arangodb.shaded.vertx.core.impl.future;
import com.arangodb.shaded.vertx.core.AsyncResult;
import com.arangodb.shaded.vertx.core.Future;
import com.arangodb.shaded.vertx.core.Handler;
import com.arangodb.shaded.vertx.core.impl.ContextInternal;
import com.arangodb.shaded.vertx.core.impl.NoStackTraceThrowable;
import java.util.ArrayList;
import java.util.Objects;
/**
* Future implementation.
*
* @author Julien Viet
*/
class FutureImpl extends FutureBase {
private static final Object NULL_VALUE = new Object();
private Object value;
private Listener listener;
/**
* Create a future that hasn't completed yet
*/
FutureImpl() {
super();
}
/**
* Create a future that hasn't completed yet
*/
FutureImpl(ContextInternal context) {
super(context);
}
/**
* The result of the operation. This will be null if the operation failed.
*/
public synchronized T result() {
return value instanceof CauseHolder ? null : value == NULL_VALUE ? null : (T) value;
}
/**
* An exception describing failure. This will be null if the operation succeeded.
*/
public synchronized Throwable cause() {
return value instanceof CauseHolder ? ((CauseHolder)value).cause : null;
}
/**
* Did it succeed?
*/
public synchronized boolean succeeded() {
return value != null && !(value instanceof CauseHolder);
}
/**
* Did it fail?
*/
public synchronized boolean failed() {
return value instanceof CauseHolder;
}
/**
* Has it completed?
*/
public synchronized boolean isComplete() {
return value != null;
}
@Override
public Future onSuccess(Handler handler) {
Objects.requireNonNull(handler, "No null handler accepted");
addListener(new Listener() {
@Override
public void onSuccess(T value) {
try {
handler.handle(value);
} catch (Throwable t) {
if (context != null) {
context.reportException(t);
} else {
throw t;
}
}
}
@Override
public void onFailure(Throwable failure) {
}
});
return this;
}
@Override
public Future onFailure(Handler handler) {
Objects.requireNonNull(handler, "No null handler accepted");
addListener(new Listener() {
@Override
public void onSuccess(T value) {
}
@Override
public void onFailure(Throwable failure) {
try {
handler.handle(failure);
} catch (Throwable t) {
if (context != null) {
context.reportException(t);
} else {
throw t;
}
}
}
});
return this;
}
@Override
public Future onComplete(Handler> handler) {
Objects.requireNonNull(handler, "No null handler accepted");
Listener listener;
if (handler instanceof Listener) {
listener = (Listener) handler;
} else {
listener = new Listener() {
@Override
public void onSuccess(T value) {
try {
handler.handle(FutureImpl.this);
} catch (Throwable t) {
if (context != null) {
context.reportException(t);
} else {
throw t;
}
}
}
@Override
public void onFailure(Throwable failure) {
try {
handler.handle(FutureImpl.this);
} catch (Throwable t) {
if (context != null) {
context.reportException(t);
} else {
throw t;
}
}
}
};
}
addListener(listener);
return this;
}
@Override
public void addListener(Listener listener) {
Object v;
synchronized (this) {
v = value;
if (v == null) {
if (this.listener == null) {
this.listener = listener;
} else {
ListenerArray listeners;
if (this.listener instanceof FutureImpl.ListenerArray) {
listeners = (ListenerArray) this.listener;
} else {
listeners = new ListenerArray<>();
listeners.add(this.listener);
this.listener = listeners;
}
listeners.add(listener);
}
return;
}
}
if (v instanceof CauseHolder) {
emitFailure(((CauseHolder)v).cause, listener);
} else {
if (v == NULL_VALUE) {
v = null;
}
emitSuccess((T) v, listener);
}
}
public boolean tryComplete(T result) {
Listener l;
synchronized (this) {
if (value != null) {
return false;
}
value = result == null ? NULL_VALUE : result;
l = listener;
listener = null;
}
if (l != null) {
emitSuccess(result, l);
}
return true;
}
public boolean tryFail(Throwable cause) {
if (cause == null) {
cause = new NoStackTraceThrowable(null);
}
Listener l;
synchronized (this) {
if (value != null) {
return false;
}
value = new CauseHolder(cause);
l = listener;
listener = null;
}
if (l != null) {
emitFailure(cause, l);
}
return true;
}
@Override
public String toString() {
synchronized (this) {
if (value instanceof CauseHolder) {
return "Future{cause=" + ((CauseHolder)value).cause.getMessage() + "}";
}
if (value != null) {
if (value == NULL_VALUE) {
return "Future{result=null}";
}
StringBuilder sb = new StringBuilder("Future{result=");
formatValue(value, sb);
sb.append("}");
return sb.toString();
}
return "Future{unresolved}";
}
}
protected void formatValue(Object value, StringBuilder sb) {
sb.append(value);
}
private static class ListenerArray extends ArrayList> implements Listener {
@Override
public void onSuccess(T value) {
for (Listener handler : this) {
handler.onSuccess(value);
}
}
@Override
public void onFailure(Throwable failure) {
for (Listener handler : this) {
handler.onFailure(failure);
}
}
}
private static class CauseHolder {
private final Throwable cause;
CauseHolder(Throwable cause) {
this.cause = cause;
}
}
}