Skip to content

Commit

Permalink
Fix FutureIml tryComplete.
Browse files Browse the repository at this point in the history
When complete error is regarded as a normal result, the Listener's complete result is inconsistent
  • Loading branch information
wang007 authored and vietj committed May 17, 2021
1 parent 1e95256 commit c2c5970
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
27 changes: 18 additions & 9 deletions src/main/java/io/vertx/core/impl/future/FutureImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,28 +50,28 @@ class FutureImpl<T> extends FutureBase<T> {
* The result of the operation. This will be null if the operation failed.
*/
public synchronized T result() {
return value instanceof Throwable ? null : value == NULL_VALUE ? null : (T) value;
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 Throwable ? (Throwable) value : null;
return value instanceof CauseHolder ? ((CauseHolder)value).cause : null;
}

/**
* Did it succeed?
*/
public synchronized boolean succeeded() {
return value != null && !(value instanceof Throwable);
return value != null && !(value instanceof CauseHolder);
}

/**
* Did it fail?
*/
public synchronized boolean failed() {
return value instanceof Throwable;
return value instanceof CauseHolder;
}

/**
Expand Down Expand Up @@ -155,8 +155,8 @@ public void addListener(Listener<T> listener) {
return;
}
}
if (v instanceof Throwable) {
emitFailure((Throwable) v, listener);
if (v instanceof CauseHolder) {
emitFailure(((CauseHolder)v).cause, listener);
} else {
if (v == NULL_VALUE) {
v = null;
Expand Down Expand Up @@ -190,7 +190,7 @@ public boolean tryFail(Throwable cause) {
if (value != null) {
return false;
}
value = cause;
value = new CauseHolder(cause);
l = listener;
listener = null;
}
Expand All @@ -203,8 +203,8 @@ public boolean tryFail(Throwable cause) {
@Override
public String toString() {
synchronized (this) {
if (value instanceof Throwable) {
return "Future{cause=" + ((Throwable)value).getMessage() + "}";
if (value instanceof CauseHolder) {
return "Future{cause=" + ((CauseHolder)value).cause.getMessage() + "}";
}
if (value != null) {
if (value == NULL_VALUE) {
Expand Down Expand Up @@ -237,4 +237,13 @@ public void onFailure(Throwable failure) {
}
}
}

private static class CauseHolder {

private final Throwable cause;

CauseHolder(Throwable cause) {
this.cause = cause;
}
}
}
15 changes: 15 additions & 0 deletions src/test/java/io/vertx/core/FutureTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,21 @@ public void testFailureFutureWithNullFailure() {
assertNull(failure.getMessage());
}

@Test
public void testCompleteCause() {
Throwable object = new RuntimeException();
Promise<Throwable> promise = Promise.promise();
AtomicReference<Boolean> r1 = new AtomicReference<>();
AtomicReference<Boolean> r2 = new AtomicReference<>();
promise.future().onSuccess(v -> r1.set(true)).onFailure(v -> r1.set(false));
Checker<Throwable> checker = new Checker<>(promise.future());
promise.complete(object);
checker.assertSucceeded(object);
promise.future().onSuccess(v -> r2.set(true)).onFailure(v -> r2.set(false));
assertTrue(r1.get());
assertTrue(r2.get());
}

@Test
public void testComposeSuccessToSuccess() {
AtomicReference<String> ref = new AtomicReference<>();
Expand Down

0 comments on commit c2c5970

Please sign in to comment.