From 205a183db71ea0f64469c1a79700d59bda1e7a10 Mon Sep 17 00:00:00 2001 From: kske Date: Mon, 12 Jul 2021 10:19:04 +0200 Subject: [PATCH] Allow nested dispatches by keeping track of nesting count --- .../java/dev/kske/eventbus/core/EventBus.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java b/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java index 2711e5d..27bb4fb 100644 --- a/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java +++ b/event-bus-core/src/main/java/dev/kske/eventbus/core/EventBus.java @@ -27,7 +27,21 @@ public final class EventBus { */ private static final class DispatchState { - boolean isDispatching, isCancelled; + /** + * Indicates that the last event handler invoked has called {@link EventBus#cancel}. In that + * case, the event is not dispatched further. + * + * @since 0.1.0 + */ + boolean isCancelled; + + /** + * Is incremented when {@link EventBus#dispatch(Object)} is invoked and decremented when it + * finishes. This allows keeping track of nested dispatches. + * + * @since 1.2.0 + */ + int nestingCount; } /** @@ -79,9 +93,11 @@ public final class EventBus { Objects.requireNonNull(event); logger.log(Level.INFO, "Dispatching event {0}", event); - // Set dispatch state + // Look up dispatch state var state = dispatchState.get(); - state.isDispatching = true; + + // Increment nesting count (becomes > 1 during nested dispatches) + ++state.nestingCount; Iterator handlers = getHandlersFor(event.getClass()); if (handlers.hasNext()) { @@ -118,8 +134,8 @@ public final class EventBus { dispatch(new DeadEvent(this, event)); } - // Reset dispatch state - state.isDispatching = false; + // Decrement nesting count (becomes 0 when all dispatches on the thread are finished) + --state.nestingCount; logger.log(Level.DEBUG, "Finished dispatching event {0}", event); } @@ -155,7 +171,7 @@ public final class EventBus { */ public void cancel() { var state = dispatchState.get(); - if (state.isDispatching && !state.isCancelled) + if (state.nestingCount > 0 && !state.isCancelled) state.isCancelled = true; else throw new EventBusException("Calling thread not an active dispatching thread!");