Skip to content

Commit

Permalink
Future fail/complete returns boolean instead of throwing an IllegalSt…
Browse files Browse the repository at this point in the history
…ateException - fixes #1824
  • Loading branch information
vietj committed Feb 17, 2017
1 parent cf3bd82 commit e5bca47
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 105 deletions.
13 changes: 13 additions & 0 deletions src/main/java/io/vertx/core/CompositeFuture.java
Expand Up @@ -185,6 +185,19 @@ static CompositeFuture join(List<Future> futures) {
@Override
CompositeFuture setHandler(Handler<AsyncResult<CompositeFuture>> handler);

/**
* @return false
*/
@Override
boolean complete();

/**
* @return false
*/
@Override
boolean complete(CompositeFuture result);


/**
* Returns a cause of a wrapped future
*
Expand Down
24 changes: 13 additions & 11 deletions src/main/java/io/vertx/core/Future.java
Expand Up @@ -109,33 +109,35 @@ static <T> Future<T> failedFuture(String failureMessage) {
Future<T> setHandler(Handler<AsyncResult<T>> handler);

/**
* Set the result. Any handler will be called, if there is one, and the future will be marked as completed.
* Try to set the result. When it happens, any handler will be called, if there is one, and the future will be marked as completed.
*
* @param result the result
* @throws IllegalStateException when the future is already completed
* @return false when the future is already completed
*/
void complete(T result);
boolean complete(T result);

/**
* Set a null result. Any handler will be called, if there is one, and the future will be marked as completed.
* Try to set the result. When it happens, any handler will be called, if there is one, and the future will be marked as completed.
*
* @throws IllegalStateException when the future is already completed
* @return false when the future is already completed
*/
void complete();
boolean complete();

/**
* Set the failure. Any handler will be called, if there is one, and the future will be marked as completed.
* Try to set the failure. When it happens, any handler will be called, if there is one, and the future will be marked as completed.
*
* @param throwable the failure cause
* @param cause the failure cause
* @return false when the future is already completed
*/
void fail(Throwable throwable);
boolean fail(Throwable cause);

/**
* Set the failure. Any handler will be called, if there is one, and the future will be marked as completed.
* Try to set the failure. When it happens, any handler will be called, if there is one, and the future will be marked as completed.
*
* @param failureMessage the failure message
* @return false when the future is already completed
*/
void fail(String failureMessage);
boolean fail(String failureMessage);

/**
* The result of the operation. This will be null if the operation failed.
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/io/vertx/core/impl/CloseHooks.java
Expand Up @@ -90,9 +90,7 @@ void run(Handler<AsyncResult<Void>> completionHandler) {
hook.close(a.completer());
} catch (Throwable t) {
log.warn("Failed to run close hooks", t);
if (!a.isComplete()) {
a.fail(t);
}
a.fail(t);
}
}
} else {
Expand Down
61 changes: 24 additions & 37 deletions src/main/java/io/vertx/core/impl/CompositeFutureImpl.java
Expand Up @@ -22,13 +22,14 @@
import io.vertx.core.Handler;

import java.util.function.Function;
import java.util.function.Predicate;

/**
* @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
*/
public class CompositeFutureImpl implements CompositeFuture, Handler<AsyncResult<CompositeFuture>> {

private static final Handler<AsyncResult<CompositeFuture>> NO_HANDLER = c -> {};

public static CompositeFuture all(Future<?>... results) {
CompositeFutureImpl composite = new CompositeFutureImpl(results);
int len = results.length;
Expand All @@ -39,13 +40,13 @@ public static CompositeFuture all(Future<?>... results) {
synchronized (composite) {
composite.count++;
if (!composite.isComplete() && composite.count == len) {
handler = composite.setSucceeded();
handler = composite.setCompleted(null);
}
}
} else {
synchronized (composite) {
if (!composite.isComplete()) {
handler = composite.setFailed(ar.cause());
handler = composite.setCompleted(ar.cause());
}
}
}
Expand All @@ -55,7 +56,7 @@ public static CompositeFuture all(Future<?>... results) {
});
}
if (len == 0) {
composite.setSucceeded();
composite.setCompleted(null);
}
return composite;
}
Expand All @@ -69,14 +70,14 @@ public static CompositeFuture any(Future<?>... results) {
if (ar.succeeded()) {
synchronized (composite) {
if (!composite.isComplete()) {
handler = composite.setSucceeded();
handler = composite.setCompleted(null);
}
}
} else {
synchronized (composite) {
composite.count++;
if (!composite.isComplete() && composite.count == len) {
handler = composite.setFailed(ar.cause());
handler = composite.setCompleted(ar.cause());
}
}
}
Expand All @@ -86,7 +87,7 @@ public static CompositeFuture any(Future<?>... results) {
});
}
if (results.length == 0) {
composite.setSucceeded();
composite.setCompleted(null);
}
return composite;
}
Expand Down Expand Up @@ -116,11 +117,7 @@ private static CompositeFuture join(Function<CompositeFuture, Throwable> pred,
if (!composite.isComplete() && composite.count == len) {
// Take decision here
Throwable failure = pred.apply(composite);
if (failure == null) {
handler = composite.setSucceeded();
} else {
handler = composite.setFailed(failure);
}
handler = composite.setCompleted(failure);
}
}
if (handler != null) {
Expand All @@ -129,7 +126,7 @@ private static CompositeFuture join(Function<CompositeFuture, Throwable> pred,
});
}
if (len == 0) {
composite.setSucceeded();
composite.setCompleted(null);
}
return composite;
}
Expand Down Expand Up @@ -220,49 +217,39 @@ public synchronized CompositeFuture result() {
}

@Override
public void complete(CompositeFuture result) {
Handler<AsyncResult<CompositeFuture>> handler = setSucceeded();
if (handler != null) {
handler.handle(this);
}
public boolean complete(CompositeFuture result) {
return false;
}

@Override
public void complete() {
complete(null);
public boolean complete() {
return false;
}

@Override
public void fail(Throwable throwable) {
Handler<AsyncResult<CompositeFuture>> handler = setFailed(throwable);
public boolean fail(Throwable cause) {
Handler<AsyncResult<CompositeFuture>> handler = setCompleted(cause);
if (handler != null) {
handler.handle(this);
return true;
} else {
return false;
}
}

@Override
public void fail(String failureMessage) {
fail(new NoStackTraceThrowable(failureMessage));
public boolean fail(String failureMessage) {
return fail(new NoStackTraceThrowable(failureMessage));
}

private Handler<AsyncResult<CompositeFuture>> setFailed(Throwable cause) {
private Handler<AsyncResult<CompositeFuture>> setCompleted(Throwable cause) {
synchronized (this) {
if (completed) {
throw new IllegalStateException("Result is already complete: " + (this.cause == null ? "succeeded" : "failed"));
return null;
}
this.completed = true;
this.cause = cause;
return handler;
}
}

private Handler<AsyncResult<CompositeFuture>> setSucceeded() {
synchronized (this) {
if (completed) {
throw new IllegalStateException("Result is already complete: " + (this.cause == null ? "succeeded" : "failed"));
}
this.completed = true;
return handler;
return handler != null ? handler : NO_HANDLER;
}
}

Expand Down
39 changes: 17 additions & 22 deletions src/main/java/io/vertx/core/impl/FutureImpl.java
Expand Up @@ -101,19 +101,20 @@ public Future<T> setHandler(Handler<AsyncResult<T>> handler) {
return this;
}

/**
* Set the result. Any handler will be called, if there is one
*/
public void complete(T result) {
checkComplete();
@Override
public boolean complete(T result) {
if (succeeded || failed) {
return false;
}
this.result = result;
succeeded = true;
checkCallHandler();
return true;
}

@Override
public void complete() {
complete(null);
public boolean complete() {
return complete(null);
}

public void handle(Future<T> ar) {
Expand All @@ -138,31 +139,25 @@ public void handle(AsyncResult<T> ar) {
}
}

/**
* Set the failure. Any handler will be called, if there is one
*/
public void fail(Throwable throwable) {
checkComplete();
this.throwable = throwable != null ? throwable : new NoStackTraceThrowable(null);
@Override
public boolean fail(Throwable cause) {
if (succeeded || failed) {
return false;
}
this.throwable = cause != null ? cause : new NoStackTraceThrowable(null);
failed = true;
checkCallHandler();
return true;
}

@Override
public void fail(String failureMessage) {
fail(new NoStackTraceThrowable(failureMessage));
public boolean fail(String failureMessage) {
return fail(new NoStackTraceThrowable(failureMessage));
}

private void checkCallHandler() {
if (handler != null && isComplete()) {
handler.handle(this);
}
}

private void checkComplete() {
if (succeeded || failed) {
throw new IllegalStateException("Result is already complete: " + (succeeded ? "succeeded" : "failed"));
}
}

}

0 comments on commit e5bca47

Please sign in to comment.