mirror of
https://github.com/jlengrand/vert.x.git
synced 2026-03-10 08:51:19 +00:00
Future should handle multiple handlers instead of a single - see #3174
This commit is contained in:
@@ -15,6 +15,8 @@ import io.vertx.core.AsyncResult;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.core.Promise;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
class FutureImpl<T> implements Promise<T>, Future<T> {
|
||||
|
||||
@@ -33,14 +35,14 @@ class FutureImpl<T> implements Promise<T>, Future<T> {
|
||||
/**
|
||||
* The result of the operation. This will be null if the operation failed.
|
||||
*/
|
||||
public T result() {
|
||||
public synchronized T result() {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* An exception describing failure. This will be null if the operation succeeded.
|
||||
*/
|
||||
public Throwable cause() {
|
||||
public synchronized Throwable cause() {
|
||||
return throwable;
|
||||
}
|
||||
|
||||
@@ -69,17 +71,41 @@ class FutureImpl<T> implements Promise<T>, Future<T> {
|
||||
* Set a handler for the result. It will get called when it's complete
|
||||
*/
|
||||
public Future<T> setHandler(Handler<AsyncResult<T>> handler) {
|
||||
boolean callHandler;
|
||||
Objects.requireNonNull(handler, "No null handler accepted");
|
||||
synchronized (this) {
|
||||
callHandler = isComplete();
|
||||
if (!callHandler) {
|
||||
this.handler = handler;
|
||||
if (!isComplete()) {
|
||||
if (this.handler == null) {
|
||||
this.handler = handler;
|
||||
} else {
|
||||
addHandler(handler);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
if (callHandler) {
|
||||
dispatch(handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addHandler(Handler<AsyncResult<T>> h) {
|
||||
Handlers<T> handlers;
|
||||
if (handler instanceof Handlers) {
|
||||
handlers = (Handlers<T>) handler;
|
||||
} else {
|
||||
handlers = new Handlers<>();
|
||||
handlers.add(handler);
|
||||
handler = handlers;
|
||||
}
|
||||
handlers.add(h);
|
||||
}
|
||||
|
||||
protected void dispatch(Handler<AsyncResult<T>> handler) {
|
||||
if (handler instanceof Handlers) {
|
||||
for (Handler<AsyncResult<T>> h : (Handlers<T>)handler) {
|
||||
h.handle(this);
|
||||
}
|
||||
} else {
|
||||
handler.handle(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -123,7 +149,7 @@ class FutureImpl<T> implements Promise<T>, Future<T> {
|
||||
handler = null;
|
||||
}
|
||||
if (h != null) {
|
||||
h.handle(this);
|
||||
dispatch(h);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -195,4 +221,14 @@ class FutureImpl<T> implements Promise<T>, Future<T> {
|
||||
return "Future{unresolved}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class Handlers<T> extends ArrayList<Handler<AsyncResult<T>>> implements Handler<AsyncResult<T>> {
|
||||
@Override
|
||||
public void handle(AsyncResult<T> res) {
|
||||
for (Handler<AsyncResult<T>> handler : this) {
|
||||
handler.handle(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,22 @@ public class FutureTest extends VertxTestBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetNullHandler() throws Exception {
|
||||
Promise<String> promise = Promise.promise();
|
||||
try {
|
||||
promise.future().setHandler(null);
|
||||
fail();
|
||||
} catch (NullPointerException ignore) {
|
||||
}
|
||||
promise.complete();
|
||||
try {
|
||||
promise.future().setHandler(null);
|
||||
fail();
|
||||
} catch (NullPointerException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCallSetHandlerBeforeCompletion() {
|
||||
AtomicBoolean called = new AtomicBoolean();
|
||||
@@ -1363,4 +1379,49 @@ public class FutureTest extends VertxTestBase {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeveralHandlers1() {
|
||||
waitFor(2);
|
||||
Promise<String> promise = Promise.promise();
|
||||
Future<String> fut = promise.future();
|
||||
fut.setHandler(ar -> {
|
||||
complete();
|
||||
});
|
||||
fut.setHandler(ar -> {
|
||||
complete();
|
||||
});
|
||||
promise.complete();
|
||||
await();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeveralHandlers2() {
|
||||
waitFor(2);
|
||||
Promise<String> promise = Promise.promise();
|
||||
promise.complete();
|
||||
Future<String> fut = promise.future();
|
||||
fut.setHandler(ar -> {
|
||||
complete();
|
||||
});
|
||||
fut.setHandler(ar -> {
|
||||
complete();
|
||||
});
|
||||
await();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeveralHandlers3() {
|
||||
waitFor(2);
|
||||
Promise<String> promise = Promise.promise();
|
||||
Future<String> fut = promise.future();
|
||||
fut.setHandler(ar -> {
|
||||
complete();
|
||||
});
|
||||
promise.complete();
|
||||
fut.setHandler(ar -> {
|
||||
complete();
|
||||
});
|
||||
await();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user