mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-13 19:51:27 +01:00
Use ClassValue to store event handles
This commit is contained in:
parent
f9367ef4a6
commit
5b3cb709d6
@ -20,7 +20,13 @@ import java.util.function.Consumer;
|
|||||||
non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
||||||
private static final Object GLOBAL_CHILD_LOCK = new Object();
|
private static final Object GLOBAL_CHILD_LOCK = new Object();
|
||||||
|
|
||||||
private final Map<Class<? extends T>, Handle<T>> handleMap = new ConcurrentHashMap<>();
|
private final ClassValue<Handle<T>> handleMap = new ClassValue<>() {
|
||||||
|
@Override
|
||||||
|
protected Handle<T> computeValue(Class<?> type) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return new Handle<>((Class<T>) type);
|
||||||
|
}
|
||||||
|
};
|
||||||
private final Map<Class<? extends T>, ListenerEntry<T>> listenerMap = new ConcurrentHashMap<>();
|
private final Map<Class<? extends T>, ListenerEntry<T>> listenerMap = new ConcurrentHashMap<>();
|
||||||
private final Set<EventNodeImpl<T>> children = new CopyOnWriteArraySet<>();
|
private final Set<EventNodeImpl<T>> children = new CopyOnWriteArraySet<>();
|
||||||
private final Map<Object, EventNodeImpl<T>> mappedNodeCache = new WeakHashMap<>();
|
private final Map<Object, EventNodeImpl<T>> mappedNodeCache = new WeakHashMap<>();
|
||||||
@ -44,11 +50,7 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <E extends T> @NotNull ListenerHandle<E> getHandle(@NotNull Class<E> handleType) {
|
public <E extends T> @NotNull ListenerHandle<E> getHandle(@NotNull Class<E> handleType) {
|
||||||
Handle<E> handle = (Handle<E>) handleMap.get(handleType);
|
return (ListenerHandle<E>) handleMap.get(handleType);
|
||||||
if (handle != null) return handle;
|
|
||||||
var tmp = new Handle<>(this, (Class<T>) handleType);
|
|
||||||
handle = (Handle<E>) handleMap.putIfAbsent(handleType, tmp);
|
|
||||||
return handle != null ? handle : (ListenerHandle<E>) tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -273,8 +275,8 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
|
|
||||||
private void invalidateEvent(Class<? extends T> eventClass) {
|
private void invalidateEvent(Class<? extends T> eventClass) {
|
||||||
forTargetEvents(eventClass, type -> {
|
forTargetEvents(eventClass, type -> {
|
||||||
Handle<? super T> handle = handleMap.get(type);
|
ListenerHandle<T> handle = getHandle((Class<T>) type);
|
||||||
if (handle != null) Handle.UPDATED.setRelease(handle, false);
|
Handle.UPDATED.setRelease(handle, false);
|
||||||
});
|
});
|
||||||
final EventNodeImpl<? super T> parent = this.parent;
|
final EventNodeImpl<? super T> parent = this.parent;
|
||||||
if (parent != null) parent.invalidateEvent(eventClass);
|
if (parent != null) parent.invalidateEvent(eventClass);
|
||||||
@ -304,25 +306,24 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
final Set<Consumer<T>> bindingConsumers = new CopyOnWriteArraySet<>();
|
final Set<Consumer<T>> bindingConsumers = new CopyOnWriteArraySet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class Handle<E extends Event> implements ListenerHandle<E> {
|
@SuppressWarnings("unchecked")
|
||||||
|
final class Handle<E extends Event> implements ListenerHandle<E> {
|
||||||
private static final VarHandle UPDATED;
|
private static final VarHandle UPDATED;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
UPDATED = MethodHandles.lookup().findVarHandle(Handle.class, "updated", boolean.class);
|
UPDATED = MethodHandles.lookup().findVarHandle(EventNodeImpl.Handle.class, "updated", boolean.class);
|
||||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final EventNodeImpl<E> node;
|
|
||||||
private final Class<E> eventType;
|
private final Class<E> eventType;
|
||||||
private Consumer<E> listener = null;
|
private Consumer<E> listener = null;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private boolean updated; // Use the UPDATED var handle
|
private boolean updated; // Use the UPDATED var handle
|
||||||
|
|
||||||
Handle(EventNodeImpl<E> node, Class<E> eventType) {
|
Handle(Class<E> eventType) {
|
||||||
this.node = node;
|
|
||||||
this.eventType = eventType;
|
this.eventType = eventType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,6 +355,7 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable Consumer<E> createConsumer() {
|
private @Nullable Consumer<E> createConsumer() {
|
||||||
|
var node = (EventNodeImpl<E>) EventNodeImpl.this;
|
||||||
// Standalone listeners
|
// Standalone listeners
|
||||||
List<Consumer<E>> listeners = new ArrayList<>();
|
List<Consumer<E>> listeners = new ArrayList<>();
|
||||||
forTargetEvents(eventType, type -> {
|
forTargetEvents(eventType, type -> {
|
||||||
@ -444,6 +446,7 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
* The goal is to limit the amount of map lookup.
|
* The goal is to limit the amount of map lookup.
|
||||||
*/
|
*/
|
||||||
private @Nullable Consumer<E> mappedConsumer() {
|
private @Nullable Consumer<E> mappedConsumer() {
|
||||||
|
var node = (EventNodeImpl<E>) EventNodeImpl.this;
|
||||||
final var mappedNodeCache = node.mappedNodeCache;
|
final var mappedNodeCache = node.mappedNodeCache;
|
||||||
if (mappedNodeCache.isEmpty()) return null;
|
if (mappedNodeCache.isEmpty()) return null;
|
||||||
Set<EventFilter<E, ?>> filters = new HashSet<>(mappedNodeCache.size());
|
Set<EventFilter<E, ?>> filters = new HashSet<>(mappedNodeCache.size());
|
||||||
@ -486,6 +489,7 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void callListener(@NotNull EventListener<E> listener, E event) {
|
void callListener(@NotNull EventListener<E> listener, E event) {
|
||||||
|
var node = (EventNodeImpl<E>) EventNodeImpl.this;
|
||||||
EventListener.Result result = listener.run(event);
|
EventListener.Result result = listener.run(event);
|
||||||
if (result == EventListener.Result.EXPIRED) {
|
if (result == EventListener.Result.EXPIRED) {
|
||||||
node.removeListener(listener);
|
node.removeListener(listener);
|
||||||
|
Loading…
Reference in New Issue
Block a user