清理 EventManager (#5381)

This commit is contained in:
Glavo
2026-02-01 16:09:31 +08:00
committed by GitHub
parent 17be25c036
commit a524ba8506

View File

@@ -17,31 +17,31 @@
*/ */
package org.jackhuang.hmcl.event; package org.jackhuang.hmcl.event;
import org.jackhuang.hmcl.util.SimpleMultimap;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.EnumMap; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer; import java.util.function.Consumer;
/// @author huangyuhui /// @author huangyuhui
public final class EventManager<T extends Event> { public final class EventManager<T extends Event> {
private static final int PRIORITY_COUNT = EventPriority.values().length;
private final ReentrantLock lock = new ReentrantLock(); private final ReentrantLock lock = new ReentrantLock();
private final SimpleMultimap<EventPriority, Consumer<T>, CopyOnWriteArraySet<Consumer<T>>> handlers @SuppressWarnings("unchecked")
= new SimpleMultimap<>(() -> new EnumMap<>(EventPriority.class), CopyOnWriteArraySet::new); private final CopyOnWriteArrayList<Consumer<T>>[] allHandlers = (CopyOnWriteArrayList<Consumer<T>>[]) new CopyOnWriteArrayList<?>[PRIORITY_COUNT];
@Contract("_ -> param1") @Contract("_ -> param1")
public Consumer<T> registerWeak(Consumer<T> consumer) { public Consumer<T> registerWeak(Consumer<T> consumer) {
register(new WeakListener(consumer)); register(new WeakListener<>(new WeakReference<>(consumer)));
return consumer; return consumer;
} }
@Contract("_, _ -> param1") @Contract("_, _ -> param1")
public Consumer<T> registerWeak(Consumer<T> consumer, EventPriority priority) { public Consumer<T> registerWeak(Consumer<T> consumer, EventPriority priority) {
register(new WeakListener(consumer), priority); register(new WeakListener<>(new WeakReference<>(consumer)), priority);
return consumer; return consumer;
} }
@@ -52,7 +52,12 @@ public final class EventManager<T extends Event> {
public void register(Consumer<T> consumer, EventPriority priority) { public void register(Consumer<T> consumer, EventPriority priority) {
lock.lock(); lock.lock();
try { try {
handlers.get(priority).add(consumer); var handlers = allHandlers[priority.ordinal()];
if (handlers == null) {
handlers = new CopyOnWriteArrayList<>();
allHandlers[priority.ordinal()] = handlers;
}
handlers.add(consumer);
} finally { } finally {
lock.unlock(); lock.unlock();
} }
@@ -69,9 +74,21 @@ public final class EventManager<T extends Event> {
public Event.Result fireEvent(T event) { public Event.Result fireEvent(T event) {
lock.lock(); lock.lock();
try { try {
for (EventPriority priority : EventPriority.values()) { for (var handlers : allHandlers) {
for (Consumer<T> handler : handlers.get(priority)) if (handlers != null) {
handler.accept(event); for (Consumer<T> handler : handlers) {
if (handler instanceof WeakListener<T> weakListener) {
Consumer<T> consumer = weakListener.ref.get();
if (consumer != null) {
consumer.accept(event);
} else {
handlers.remove(weakListener);
}
} else {
handler.accept(event);
}
}
}
} }
} finally { } finally {
lock.unlock(); lock.unlock();
@@ -80,30 +97,12 @@ public final class EventManager<T extends Event> {
return event.hasResult() ? event.getResult() : Event.Result.DEFAULT; return event.hasResult() ? event.getResult() : Event.Result.DEFAULT;
} }
public void unregister(Consumer<T> consumer) { private record WeakListener<T>(WeakReference<Consumer<T>> ref) implements Consumer<T> {
lock.lock();
try {
handlers.removeValue(consumer);
} finally {
lock.unlock();
}
}
private final class WeakListener implements Consumer<T> {
private final WeakReference<Consumer<T>> ref;
public WeakListener(Consumer<T> listener) {
this.ref = new WeakReference<>(listener);
}
@Override @Override
public void accept(T t) { public void accept(T t) {
Consumer<T> listener = ref.get(); Consumer<T> listener = ref.get();
if (listener == null) { if (listener != null)
unregister(this);
} else {
listener.accept(t); listener.accept(t);
}
} }
} }
} }