diff --git a/build.gradle b/build.gradle index e9b879aa..1fb001d1 100644 --- a/build.gradle +++ b/build.gradle @@ -109,7 +109,7 @@ dependencies { modCompileOnly("maven.modrinth:chunky:1.4.36-fabric") modRuntimeOnlyMsk("maven.modrinth:chunky:1.4.36-fabric") - modRuntimeOnlyMsk("maven.modrinth:spark:1.10.138-fabric") + modRuntimeOnlyMsk("maven.modrinth:spark:1.10.139-fabric") modRuntimeOnlyMsk("maven.modrinth:fabric-permissions-api:0.3.3") //modRuntimeOnly("maven.modrinth:nsight-loader:1.2.0") diff --git a/src/main/java/me/cortex/voxy/common/thread/ServiceThreadPool.java b/src/main/java/me/cortex/voxy/common/thread/ServiceThreadPool.java index 29c2cb6a..d8eb8107 100644 --- a/src/main/java/me/cortex/voxy/common/thread/ServiceThreadPool.java +++ b/src/main/java/me/cortex/voxy/common/thread/ServiceThreadPool.java @@ -272,7 +272,7 @@ public class ServiceThreadPool { } //Sleep for a bit after running a job, yeild the thread - Thread.yield(); + //Thread.yield(); break; } } diff --git a/src/main/java/me/cortex/voxy/common/util/VolatileHolder.java b/src/main/java/me/cortex/voxy/common/util/VolatileHolder.java deleted file mode 100644 index faaf0014..00000000 --- a/src/main/java/me/cortex/voxy/common/util/VolatileHolder.java +++ /dev/null @@ -1,5 +0,0 @@ -package me.cortex.voxy.common.util; - -public class VolatileHolder { - public volatile T obj; -} diff --git a/src/main/java/me/cortex/voxy/common/world/ActiveSectionTracker.java b/src/main/java/me/cortex/voxy/common/world/ActiveSectionTracker.java index 52e17906..c71194bd 100644 --- a/src/main/java/me/cortex/voxy/common/world/ActiveSectionTracker.java +++ b/src/main/java/me/cortex/voxy/common/world/ActiveSectionTracker.java @@ -3,15 +3,13 @@ package me.cortex.voxy.common.world; import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import me.cortex.voxy.common.Logger; -import me.cortex.voxy.common.util.VolatileHolder; -import me.cortex.voxy.common.voxelization.WorldConversionFactory; -import me.cortex.voxy.common.world.other.Mapper; import org.jetbrains.annotations.Nullable; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.util.Arrays; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.StampedLock; public class ActiveSectionTracker { @@ -20,6 +18,21 @@ public class ActiveSectionTracker { public interface SectionLoader {int load(WorldSection section);} //Loaded section world cache, TODO: get rid of VolatileHolder and use something more sane + private static final class VolatileHolder { + private static final VarHandle PRE_ACQUIRE_COUNT; + private static final VarHandle POST_ACQUIRE_COUNT; + static { + try { + PRE_ACQUIRE_COUNT = MethodHandles.lookup().findVarHandle(VolatileHolder.class, "preAcquireCount", int.class); + POST_ACQUIRE_COUNT = MethodHandles.lookup().findVarHandle(VolatileHolder.class, "postAcquireCount", int.class); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + public volatile int preAcquireCount; + public volatile int postAcquireCount; + public volatile T obj; + } private final AtomicInteger loadedSections = new AtomicInteger(); private final Long2ObjectOpenHashMap>[] loadedSectionCache; @@ -102,6 +115,8 @@ public class ActiveSectionTracker { section = this.lruSecondaryCache.remove(key); this.lruLock.unlockWrite(stamp); lock.unlockRead(stamp2); + } else { + VolatileHolder.PRE_ACQUIRE_COUNT.getAndAdd(holder, 1); } //If this thread was the one to create the reference then its the thread to load the section @@ -131,8 +146,12 @@ public class ActiveSectionTracker { } else { section.primeForReuse(); } + int preAcquireCount = (int) VolatileHolder.PRE_ACQUIRE_COUNT.getAndSet(holder, 0); + section.acquire(preAcquireCount+1);//pre acquire amount + VolatileHolder.POST_ACQUIRE_COUNT.set(holder, preAcquireCount); + + //TODO: mark if the section was loaded null - section.acquire(); VarHandle.storeStoreFence();//Do not reorder setting this object holder.obj = section; VarHandle.releaseFence(); @@ -142,6 +161,7 @@ public class ActiveSectionTracker { } return section; } else { + //TODO: mark the time the loading started in nanos, then here if it has been a while, spin lock, else jump back to the executing service and do work VarHandle.fullFence(); while ((section = holder.obj) == null) { VarHandle.fullFence(); @@ -149,16 +169,22 @@ public class ActiveSectionTracker { Thread.yield(); } - //lock.lock(); - {//Dont think need to lock here - if (section.tryAcquire()) { - return section; + //Try to acquire a pre lock + if (0<((int)VolatileHolder.POST_ACQUIRE_COUNT.getAndAdd(holder, -1))) { + //We managed to acquire one of the pre locks, so just return the section + return section; + } else { + //lock.lock(); + {//Dont think need to lock here + if (section.tryAcquire()) { + return section; + } } - } - //lock.unlock(); + //lock.unlock(); - //We failed everything, try get it again - return this.acquire(key, nullOnEmpty); + //We failed everything, try get it again + return this.acquire(key, nullOnEmpty); + } } }