diff --git a/common/src/main/java/com/discordsrv/common/event/bus/EventBusImpl.java b/common/src/main/java/com/discordsrv/common/event/bus/EventBusImpl.java index 52169ec7..d9990ad9 100644 --- a/common/src/main/java/com/discordsrv/common/event/bus/EventBusImpl.java +++ b/common/src/main/java/com/discordsrv/common/event/bus/EventBusImpl.java @@ -53,6 +53,7 @@ public class EventBusImpl implements EventBus { ); private final Map> listeners = new ConcurrentHashMap<>(); + private final List allListeners = new CopyOnWriteArrayList<>(); private final DiscordSRV discordSRV; private final Logger logger; @@ -76,7 +77,7 @@ public class EventBusImpl implements EventBus { Class currentClass = listenerClass; do { for (Method method : currentClass.getDeclaredMethods()) { - checkMethod(listenerClass, method, suppressedMethods, methods, methodsByPriority); + checkMethod(eventListener, listenerClass, method, suppressedMethods, methods, methodsByPriority); } } while ((currentClass = currentClass.getSuperclass()) != null); @@ -88,10 +89,11 @@ public class EventBusImpl implements EventBus { } listeners.put(eventListener, methods); + allListeners.addAll(methods); logger.debug("Listener " + eventListener.getClass().getName() + " subscribed"); } - private void checkMethod(Class listenerClass, Method method, + private void checkMethod(Object eventListener, Class listenerClass, Method method, List suppressedMethods, List methods, EnumMap> methodsByPriority) { Subscribe annotation = method.getAnnotation(Subscribe.class); @@ -140,7 +142,7 @@ public class EventBusImpl implements EventBus { } EventPriority eventPriority = annotation.priority(); - EventListenerImpl listener = new EventListenerImpl(listenerClass, annotation, firstParameter, method); + EventListenerImpl listener = new EventListenerImpl(eventListener, listenerClass, annotation, firstParameter, method); methods.add(listener); methodsByPriority.computeIfAbsent(eventPriority, key -> new CopyOnWriteArrayList<>()) @@ -154,8 +156,11 @@ public class EventBusImpl implements EventBus { @Override public void unsubscribe(@NotNull Object eventListener) { - listeners.remove(eventListener); - logger.debug("Listener " + eventListener.getClass().getName() + " unsubscribed"); + List removed = listeners.remove(eventListener); + if (removed != null) { + allListeners.removeAll(removed); + logger.debug("Listener " + eventListener.getClass().getName() + " unsubscribed"); + } } @Override @@ -182,44 +187,42 @@ public class EventBusImpl implements EventBus { Class eventClass = event.getClass(); for (EventPriority priority : EventPriority.values()) { - for (Map.Entry> entry : listeners.entrySet()) { - Object listener = entry.getKey(); - for (EventListenerImpl eventListener : entry.getValue()) { - if (eventListener.isIgnoringCancelled() && event instanceof Cancellable && ((Cancellable) event).isCancelled()) { - continue; - } - if (eventListener.priority() != priority) { - continue; - } - if (!eventListener.eventClass().isAssignableFrom(eventClass)) { - continue; - } + for (EventListenerImpl eventListener : allListeners) { + if (eventListener.isIgnoringCancelled() && event instanceof Cancellable && ((Cancellable) event).isCancelled()) { + continue; + } + if (eventListener.priority() != priority) { + continue; + } + if (!eventListener.eventClass().isAssignableFrom(eventClass)) { + continue; + } - long startTime = System.currentTimeMillis(); - try { - eventListener.method().invoke(listener, event); - } catch (IllegalAccessException e) { - discordSRV.logger().error("Failed to access listener method: " + eventListener.methodName(), e); - } catch (InvocationTargetException e) { - discordSRV.logger().error("Failed to pass " + event.getClass().getSimpleName() + " to " + eventListener, e.getCause()); - } - long timeTaken = System.currentTimeMillis() - startTime; - logger.trace(eventListener + " took " + timeTaken + "ms to execute"); + long startTime = System.currentTimeMillis(); + try { + Object listener = eventListener.listener(); + eventListener.method().invoke(listener, event); + } catch (IllegalAccessException e) { + discordSRV.logger().error("Failed to access listener method: " + eventListener.methodName(), e); + } catch (InvocationTargetException e) { + discordSRV.logger().error("Failed to pass " + event.getClass().getSimpleName() + " to " + eventListener, e.getCause()); + } + long timeTaken = System.currentTimeMillis() - startTime; + logger.trace(eventListener + " took " + timeTaken + "ms to execute"); - for (int index = 0; index < STATES.size(); index++) { - Pair, ThreadLocal> state = STATES.get(index); + for (int index = 0; index < STATES.size(); index++) { + Pair, ThreadLocal> state = STATES.get(index); - boolean current = states.get(index); - boolean updated = state.getKey().apply(event); - states.set(index, updated); + boolean current = states.get(index); + boolean updated = state.getKey().apply(event); + states.set(index, updated); - ThreadLocal stateHolder = state.getValue(); - if (current != updated) { - if (updated) { - stateHolder.set(eventListener); - } else { - stateHolder.remove(); - } + ThreadLocal stateHolder = state.getValue(); + if (current != updated) { + if (updated) { + stateHolder.set(eventListener); + } else { + stateHolder.remove(); } } } diff --git a/common/src/main/java/com/discordsrv/common/event/bus/EventListenerImpl.java b/common/src/main/java/com/discordsrv/common/event/bus/EventListenerImpl.java index c3695b77..6855c5c7 100644 --- a/common/src/main/java/com/discordsrv/common/event/bus/EventListenerImpl.java +++ b/common/src/main/java/com/discordsrv/common/event/bus/EventListenerImpl.java @@ -27,12 +27,14 @@ import java.lang.reflect.Method; public class EventListenerImpl implements EventListener { + private final Object listener; private final Class listenerClass; private final Subscribe annotation; private final Class eventClass; private final Method method; - public EventListenerImpl(Class listenerClass, Subscribe annotation, Class eventClass, Method method) { + public EventListenerImpl(Object listener, Class listenerClass, Subscribe annotation, Class eventClass, Method method) { + this.listener = listener; this.listenerClass = listenerClass; this.annotation = annotation; this.eventClass = eventClass; @@ -47,6 +49,10 @@ public class EventListenerImpl implements EventListener { return annotation.priority(); } + public Object listener() { + return listener; + } + public Class eventClass() { return eventClass; }