From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MrHua269 Date: Fri, 12 Apr 2024 13:48:09 +0000 Subject: [PATCH] Rewrite linear region flush task dispatching diff --git a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java index e40989889f3821bb7484fc0bae5d94b033013904..dc5a5f42c9ca7a50295c18424722568a3ad33fa5 100644 --- a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java +++ b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java @@ -126,7 +126,7 @@ public class LinearRegionFile implements AbstractRegionFile, AutoCloseable { } public void flush() throws IOException { - if (isMarkedToSave()) flushWrapper(); // sync + if (getAndResetSaveMarker()) flushWrapper(); // sync } private void markToSave() { @@ -134,10 +134,18 @@ public class LinearRegionFile implements AbstractRegionFile, AutoCloseable { markedToSave.set(true); } - public boolean isMarkedToSave() { + public boolean getAndResetSaveMarker() { return markedToSave.getAndSet(false); } + public boolean isMarkedToSave(){ + return this.markedToSave.get(); + } + + public void resetSaveMarker(){ + this.markedToSave.set(false); + } + public void flushWrapper() { try { save(); diff --git a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java index f06d7767c79e465f999b2032086cc224de95152a..65435eb666b2e1cabffc145e016faa5e3b373464 100644 --- a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java +++ b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java @@ -1,17 +1,14 @@ package dev.kaiijumc.kaiiju.region; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import java.util.Queue; + +import java.util.Set; import java.util.concurrent.*; import org.bukkit.Bukkit; public class LinearRegionFileFlusher { - private final Queue savingQueue = new LinkedBlockingQueue<>(); - private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor( - new ThreadFactoryBuilder() - .setNameFormat("linear-flush-scheduler") - .build() - ); + private final Set pendingSaving = ConcurrentHashMap.newKeySet(); + private final ExecutorService executor = Executors.newFixedThreadPool( me.earthme.luminol.config.modules.misc.RegionFormatConfig.linearFlushThreads, new ThreadFactoryBuilder() @@ -19,26 +16,42 @@ public class LinearRegionFileFlusher { .build() ); + private final Executor delayedFlusher = CompletableFuture.delayedExecutor( + me.earthme.luminol.config.modules.misc.RegionFormatConfig.linearFlushFrequency, + TimeUnit.SECONDS, + executor + ); + public LinearRegionFileFlusher() { Bukkit.getLogger().info("Using " + me.earthme.luminol.config.modules.misc.RegionFormatConfig.linearFlushThreads + " threads for linear region flushing."); - scheduler.scheduleAtFixedRate(this::pollAndFlush, 0L, me.earthme.luminol.config.modules.misc.RegionFormatConfig.linearFlushFrequency, TimeUnit.SECONDS); } public void scheduleSave(LinearRegionFile regionFile) { - if (savingQueue.contains(regionFile)) return; - savingQueue.add(regionFile); - } - - private void pollAndFlush() { - while (!savingQueue.isEmpty()) { - LinearRegionFile regionFile = savingQueue.poll(); - if (!regionFile.closed && regionFile.isMarkedToSave()) - executor.execute(regionFile::flushWrapper); + if (this.pendingSaving.contains(regionFile) || !regionFile.isMarkedToSave()){ + return; } + + this.pendingSaving.add(regionFile); + this.delayedFlusher.execute(()->{ + try { + if (!regionFile.closed && regionFile.isMarkedToSave()){ + regionFile.flushWrapper(); + } + }finally { + regionFile.resetSaveMarker(); + this.pendingSaving.remove(regionFile); + } + }); } public void shutdown() { - executor.shutdown(); - scheduler.shutdown(); + this.executor.shutdown(); + for (;;) { + try { + if (this.executor.awaitTermination(5_00,TimeUnit.MILLISECONDS)) break; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } }