Properly Handle Nested Dispatches #19
@ -27,7 +27,21 @@ public final class EventBus {
|
|||||||
*/
|
*/
|
||||||
private static final class DispatchState {
|
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);
|
Objects.requireNonNull(event);
|
||||||
logger.log(Level.INFO, "Dispatching event {0}", event);
|
logger.log(Level.INFO, "Dispatching event {0}", event);
|
||||||
|
|
||||||
// Set dispatch state
|
// Look up dispatch state
|
||||||
var state = dispatchState.get();
|
var state = dispatchState.get();
|
||||||
state.isDispatching = true;
|
|
||||||
|
// Increment nesting count (becomes > 1 during nested dispatches)
|
||||||
|
++state.nestingCount;
|
||||||
|
|
||||||
Iterator<EventHandler> handlers = getHandlersFor(event.getClass());
|
Iterator<EventHandler> handlers = getHandlersFor(event.getClass());
|
||||||
if (handlers.hasNext()) {
|
if (handlers.hasNext()) {
|
||||||
@ -118,8 +134,8 @@ public final class EventBus {
|
|||||||
dispatch(new DeadEvent(this, event));
|
dispatch(new DeadEvent(this, event));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset dispatch state
|
// Decrement nesting count (becomes 0 when all dispatches on the thread are finished)
|
||||||
state.isDispatching = false;
|
--state.nestingCount;
|
||||||
|
|
||||||
logger.log(Level.DEBUG, "Finished dispatching event {0}", event);
|
logger.log(Level.DEBUG, "Finished dispatching event {0}", event);
|
||||||
}
|
}
|
||||||
@ -155,7 +171,7 @@ public final class EventBus {
|
|||||||
*/
|
*/
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
var state = dispatchState.get();
|
var state = dispatchState.get();
|
||||||
if (state.isDispatching && !state.isCancelled)
|
if (state.nestingCount > 0 && !state.isCancelled)
|
||||||
state.isCancelled = true;
|
state.isCancelled = true;
|
||||||
else
|
else
|
||||||
throw new EventBusException("Calling thread not an active dispatching thread!");
|
throw new EventBusException("Calling thread not an active dispatching thread!");
|
||||||
|
Loading…
Reference in New Issue
Block a user