From 755a7ebade3c67b73cd44104915430f31856e48a Mon Sep 17 00:00:00 2001 From: Andrew Wong <42793301+md5sha256@users.noreply.github.com> Date: Sun, 12 Jan 2025 03:12:07 +0800 Subject: [PATCH] Refactor ticker task to use a thread-safe Set implementation for tickingLocations (#4173) Fixes #3696 Fixes #4216 --- .../slimefun4/implementation/tasks/TickerTask.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java index cbf6e42eb1..91525994fb 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/tasks/TickerTask.java @@ -44,6 +44,7 @@ public class TickerTask implements Runnable { /** * This Map holds all currently actively ticking locations. + * The value of this map (Set entries) MUST be thread-safe and mutable. */ private final Map> tickingLocations = new ConcurrentHashMap<>(); @@ -329,7 +330,7 @@ public Map> getLocations() { public Set getLocations(@Nonnull Chunk chunk) { Validate.notNull(chunk, "The Chunk cannot be null!"); - Set locations = tickingLocations.getOrDefault(new ChunkPosition(chunk), new HashSet<>()); + Set locations = tickingLocations.getOrDefault(new ChunkPosition(chunk), Collections.emptySet()); return Collections.unmodifiableSet(locations); } @@ -343,7 +344,14 @@ public void enableTicker(@Nonnull Location l) { Validate.notNull(l, "Location cannot be null!"); ChunkPosition chunk = new ChunkPosition(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4); - Set newValue = new HashSet<>(); + + /* + Note that all the values in #tickingLocations must be thread-safe. + Thus, the choice is between the CHM KeySet or a synchronized set. + The CHM KeySet was chosen since it at least permits multiple concurrent + reads without blocking. + */ + Set newValue = ConcurrentHashMap.newKeySet(); Set oldValue = tickingLocations.putIfAbsent(chunk, newValue); /**