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 @Override
CompositeFuture setHandler(Handler<AsyncResult<CompositeFuture>> handler); 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 * 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); 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 * @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 * @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. * 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()); hook.close(a.completer());
} catch (Throwable t) { } catch (Throwable t) {
log.warn("Failed to run close hooks", t); log.warn("Failed to run close hooks", t);
if (!a.isComplete()) { a.fail(t);
a.fail(t);
}
} }
} }
} else { } 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 io.vertx.core.Handler;


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


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


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

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


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


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


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


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


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


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; return this;
} }


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


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


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


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


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


private void checkCallHandler() { private void checkCallHandler() {
if (handler != null && isComplete()) { if (handler != null && isComplete()) {
handler.handle(this); 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.