From 6a5fff3caab464adcd57cbf39745f530c5143173 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Thu, 23 Mar 2023 07:55:26 -0700 Subject: [PATCH] Make ClickCallbackProviderImpl thread-safe Can no longer process tasks from the main thread like that anymore, it just needs to be concurrent. --- patches/server/0004-Threaded-Regions.patch | 71 +++++++++++++++++-- ...0010-Disable-mid-tick-task-execution.patch | 2 +- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/patches/server/0004-Threaded-Regions.patch b/patches/server/0004-Threaded-Regions.patch index d54c2ad..6f8e866 100644 --- a/patches/server/0004-Threaded-Regions.patch +++ b/patches/server/0004-Threaded-Regions.patch @@ -1803,6 +1803,65 @@ index 4d9bc4a62ebae0f3707900503576c64733de639f..9ba89a4bf4ae4e42418eca18f9d8a109 this.queueIfAsyncOrRunImmediately(new Waitable() { @Override protected Void evaluate() { +diff --git a/src/main/java/io/papermc/paper/adventure/providers/ClickCallbackProviderImpl.java b/src/main/java/io/papermc/paper/adventure/providers/ClickCallbackProviderImpl.java +index 3c17001bcd3862a76a22df488bff80a0ff4d1b83..b2fffaa862df045bacb346f3cbe7eb963e104e47 100644 +--- a/src/main/java/io/papermc/paper/adventure/providers/ClickCallbackProviderImpl.java ++++ b/src/main/java/io/papermc/paper/adventure/providers/ClickCallbackProviderImpl.java +@@ -23,35 +23,42 @@ public class ClickCallbackProviderImpl implements ClickCallback.Provider { + + public static final class CallbackManager { + +- private final Map callbacks = new HashMap<>(); +- private final Queue queue = new ConcurrentLinkedQueue<>(); ++ private final java.util.concurrent.ConcurrentHashMap callbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Folia - region threading ++ // Folia - region threading + + private CallbackManager() { + } + + public UUID addCallback(final @NotNull ClickCallback callback, final ClickCallback.@NotNull Options options) { + final UUID id = UUID.randomUUID(); +- this.queue.add(new StoredCallback(callback, options, id)); ++ final StoredCallback scb = new StoredCallback(callback, options, id); // Folia - region threading ++ this.callbacks.put(scb.id(), scb); // Folia - region threading + return id; + } + + public void handleQueue(final int currentTick) { + // Evict expired entries + if (currentTick % 100 == 0) { +- this.callbacks.values().removeIf(callback -> !callback.valid()); ++ this.callbacks.values().removeIf(StoredCallback::expired); // Folia - region threading - don't read uses field + } + +- // Add entries from queue +- StoredCallback callback; +- while ((callback = this.queue.poll()) != null) { +- this.callbacks.put(callback.id(), callback); +- } ++ // Folia - region threading + } + + public void runCallback(final @NotNull Audience audience, final UUID id) { +- final StoredCallback callback = this.callbacks.get(id); +- if (callback != null && callback.valid()) { //TODO Message if expired/invalid? +- callback.takeUse(); ++ // Folia start - region threading ++ final StoredCallback[] use = new StoredCallback[1]; ++ this.callbacks.computeIfPresent(id, (final UUID keyInMap, final StoredCallback value) -> { ++ if (!value.valid()) { ++ return null; ++ } ++ use[0] = value; ++ value.takeUse(); ++ return value.valid() ? value : null; ++ }); ++ final StoredCallback callback = use[0]; ++ if (callback != null) { //TODO Message if expired/invalid? ++ // Folia end - region threading + callback.callback.accept(audience); + } + } diff --git a/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java b/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java index 6df1948b1204a7288ecb7238b6fc2a733f7d25b3..6a413abc67aa4dcbab64231be3eb13446d5cc820 100644 --- a/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java @@ -3994,10 +4053,10 @@ index 0000000000000000000000000000000000000000..3549e5f3359f38b207e189d895954420 +} diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionisedServer.java b/src/main/java/io/papermc/paper/threadedregions/RegionisedServer.java new file mode 100644 -index 0000000000000000000000000000000000000000..b40d3834fbaa032fb5ee3a9423e1b4a7d3123c29 +index 0000000000000000000000000000000000000000..4525ad9d0537406e2ca6ff8627d06c683e09a57a --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionisedServer.java -@@ -0,0 +1,352 @@ +@@ -0,0 +1,355 @@ +package io.papermc.paper.threadedregions; + +import ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue; @@ -4194,6 +4253,9 @@ index 0000000000000000000000000000000000000000..b40d3834fbaa032fb5ee3a9423e1b4a7 + + private void globalTick(final int tickCount) { + ++this.tickCount; ++ // expire invalid click command callbacks ++ io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue((int)this.tickCount); ++ + // scheduler + ((FoliaGlobalRegionScheduler)Bukkit.getGlobalRegionScheduler()).tick(); + @@ -11530,7 +11592,7 @@ index d2f0a0755317f5fa9a1ccf7db346aa77fd287d80..b07df826a3028c14b48b09dbaeccc907 // CraftBukkit start - SPIGOT-5477, MC-142590 } else if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 8ccc92836bfda8e00eea649430174dcd5664af70..58eee2965ce3e92b0f90eb7e908c6eee40052670 100644 +index 8ccc92836bfda8e00eea649430174dcd5664af70..6bf90c2a71d03788b6b15f858687372674dddc03 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -294,7 +294,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop