Allow event node handle to be garbage collected (#1835)

This commit is contained in:
iam 2023-04-23 07:07:40 -04:00 committed by GitHub
parent 8ad2c7701f
commit 79ce9570ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 3 deletions

View File

@ -8,6 +8,7 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@ -442,14 +443,15 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
final var mappedNodeCache = node.registeredMappedNode;
if (mappedNodeCache.isEmpty()) return null;
Set<EventFilter<E, ?>> filters = new HashSet<>(mappedNodeCache.size());
Map<Object, Handle<E>> handlers = new WeakHashMap<>(mappedNodeCache.size());
Map<Object, WeakReference<Handle<E>>> handlers = new WeakHashMap<>(mappedNodeCache.size());
// Retrieve all filters used to retrieve potential handlers
for (var mappedEntry : mappedNodeCache.entrySet()) {
final EventNodeImpl<E> mappedNode = mappedEntry.getValue();
final Handle<E> handle = (Handle<E>) mappedNode.getHandle(eventType);
if (!handle.hasListener()) continue; // Implicit update
filters.add(mappedNode.filter);
handlers.put(mappedEntry.getKey(), handle);
handlers.put(mappedEntry.getKey(), new WeakReference<>(handle));
}
// If at least one mapped node listen to this handle type,
// loop through them and forward to mapped node if there is a match
@ -457,7 +459,8 @@ non-sealed class EventNodeImpl<T extends Event> implements EventNode<T> {
final EventFilter<E, ?>[] filterList = filters.toArray(EventFilter[]::new);
final BiConsumer<EventFilter<E, ?>, E> mapper = (filter, event) -> {
final Object handler = filter.castHandler(event);
final Handle<E> handle = handlers.get(handler);
final WeakReference<Handle<E>> handleRef = handlers.get(handler);
final Handle<E> handle = handleRef != null ? handleRef.get() : null;
if (handle != null) handle.call(event);
};
// Specialize the consumer depending on the number of filters to avoid looping

View File

@ -1,13 +1,16 @@
package net.minestom.server.instance;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.event.instance.InstanceTickEvent;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.event.player.PlayerTickEvent;
import net.minestom.server.world.DimensionType;
import net.minestom.testing.Env;
import net.minestom.testing.EnvTest;
import org.junit.jupiter.api.Test;
import java.lang.ref.WeakReference;
import java.util.UUID;
import static net.minestom.testing.TestUtils.waitUntilCleared;
@ -80,4 +83,23 @@ public class InstanceUnregisterIntegrationTest {
chunk = null;
waitUntilCleared(ref);
}
@Test
public void testGCWithEventsLambda(Env env) {
var ref = new WeakReference<>(new InstanceContainer(UUID.randomUUID(), DimensionType.OVERWORLD));
env.process().instance().registerInstance(ref.get());
tmp(ref.get());
ref.get().tick(0);
env.process().instance().unregisterInstance(ref.get());
waitUntilCleared(ref);
}
private void tmp(InstanceContainer instanceContainer) {
instanceContainer.eventNode().addListener(InstanceTickEvent.class, (e) -> {
var uuid = instanceContainer.getUniqueId();
});
}
}