Don't use own thread for drive syncing to disk, use Minecraft's background executor instead

This commit is contained in:
DBotThePony 2023-08-16 19:39:12 +07:00
parent 8e03b4363d
commit 4430fdcb6b
Signed by: DBot
GPG Key ID: DCC23B5715498507
3 changed files with 7 additions and 54 deletions

View File

@ -142,8 +142,6 @@ public final class OverdriveThatMatters {
}
private void setup(final FMLCommonSetupEvent event) {
EVENT_BUS.addListener(EventPriority.HIGHEST, DrivePool.INSTANCE::serverStopEvent);
EVENT_BUS.addListener(EventPriority.LOWEST, DrivePool.INSTANCE::serverStartEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, DrivePool.INSTANCE::onWorldSave);
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopped);

View File

@ -6,6 +6,7 @@ import net.minecraft.ReportedException
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.NbtIo
import net.minecraft.CrashReport
import net.minecraft.Util
import net.minecraft.world.level.storage.LevelResource
import java.util.concurrent.locks.LockSupport
import net.minecraftforge.event.server.ServerAboutToStartEvent
@ -14,6 +15,7 @@ import net.minecraftforge.event.level.LevelEvent
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
import ru.dbotthepony.mc.otm.isServerThread
import java.io.File
import java.lang.ref.WeakReference
import java.util.ArrayList
@ -61,14 +63,10 @@ object DrivePool {
private val resource = LevelResource("otm_drives")
private val LOGGER = LogManager.getLogger()
private val pool = Object2ObjectOpenHashMap<UUID, WeakDriveReference>()
private var thread: Thread? = null
private var stopping = false
private val backlog = ConcurrentLinkedQueue<BacklogLine>()
private var knownBaseDirectory: File? = null
private var serverThread: Thread? = null
private val baseDirectory: File? get() {
val server = NULLABLE_MINECRAFT_SERVER ?: return null
@ -83,7 +81,7 @@ object DrivePool {
}
operator fun <T : IMatteryDrive<*>> get(id: UUID, deserializer: (CompoundTag) -> T, factory: () -> T): T {
if (!isLegalAccess())
if (!isServerThread())
throw IllegalAccessException("Can not access drive pool from outside of server thread.")
if (!SERVER_IS_LIVE)
@ -115,47 +113,11 @@ object DrivePool {
}
fun markDirty(id: UUID) {
if (isLegalAccess()) {
if (isServerThread()) {
pool[id]?.access()
}
}
/**
* Returns whenever running on server thread. Calling [get], [put] or [markDirty] will throw an exception if this returns false.
*
* If you are making your own drive for your own storage stack, feed code outside of server thread (e.g. client code) dummy disk.
*/
fun isLegalAccess(): Boolean {
return serverThread != null && Thread.currentThread() === serverThread
}
fun serverStartEvent(event: ServerAboutToStartEvent) {
if (thread?.isAlive == true) {
LOGGER.error("FMLServerStartedEvent fired twice.")
LOGGER.error("Attempting to start another DrivePool I/O thread when already running one!")
return
}
pool.clear()
serverThread = Thread.currentThread()
stopping = false
thread = Thread(null, this::run, "Overdrive That Matters DrivePool IO").also { it.start() }
}
fun serverStopEvent(event: ServerStoppingEvent) {
val thread = thread
if (thread != null && thread.isAlive) {
stopping = true
LockSupport.unpark(thread)
}
writeBacklog()
sync()
pool.clear()
}
fun onWorldSave(event: LevelEvent.Save) {
writeBacklog()
}
@ -185,14 +147,7 @@ object DrivePool {
}
if (needsSync) {
LockSupport.unpark(thread)
}
}
private fun run() {
while (!stopping) {
sync()
LockSupport.park()
Util.backgroundExecutor().execute(::sync)
}
}

View File

@ -1,6 +1,5 @@
package ru.dbotthepony.mc.otm.item
import ru.dbotthepony.mc.otm.capability.drive.DrivePool.isLegalAccess
import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional
@ -24,6 +23,7 @@ import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.tagNotNull
import ru.dbotthepony.mc.otm.isServerThread
import java.math.BigInteger
import java.util.*
@ -35,7 +35,7 @@ class PortableCondensationDriveItem(capacity: Int) :
private var uuid: UUID? = null
private val resolver = LazyOptional.of<IMatteryDrive<*>> {
if (!isLegalAccess()) {
if (!isServerThread()) {
return@of ItemMatteryDrive.DUMMY
}