diff --git a/src/main/java/me/cortex/voxy/common/world/WorldSection.java b/src/main/java/me/cortex/voxy/common/world/WorldSection.java index 63e6d7ca..6290a704 100644 --- a/src/main/java/me/cortex/voxy/common/world/WorldSection.java +++ b/src/main/java/me/cortex/voxy/common/world/WorldSection.java @@ -12,7 +12,10 @@ import java.util.concurrent.atomic.AtomicLongFieldUpdater; //Represents a loaded world section at a specific detail level // holds a 32x32x32 region of detail public final class WorldSection { - private static final int ARRAY_REUSE_CACHE_SIZE = 256; + public static final boolean VERIFY_WORLD_SECTION_EXECUTION = System.getProperty("voxy.verifyWorldSectionExecution", "true").equals("true"); + + //TODO: should make it dynamically adjust the size allowance based on memory pressure/WorldSection allocation rate (e.g. is it doing a world import) + private static final int ARRAY_REUSE_CACHE_SIZE = 300; //TODO: maybe just swap this to a ConcurrentLinkedDeque private static final Deque ARRAY_REUSE_CACHE = new ArrayDeque<>(1024); @@ -58,11 +61,22 @@ public final class WorldSection { return ((x*1235641+y)*8127451+z)*918267913+lvl; } + public boolean tryAcquire() { + int state = this.atomicState.updateAndGet(val -> { + if ((val&1) != 0) { + return val+2; + } + return val; + }); + return (state&1) != 0; + } public int acquire() { int state = this.atomicState.addAndGet(2); - if ((state&1) == 0) { - throw new IllegalStateException("Tried to acquire unloaded section"); + if (VERIFY_WORLD_SECTION_EXECUTION) { + if ((state & 1) == 0) { + throw new IllegalStateException("Tried to acquire unloaded section"); + } } return state>>1; } @@ -74,24 +88,27 @@ public final class WorldSection { //TODO: add the ability to hint to the tracker that yes the section is unloaded, try to cache it in a secondary cache since it will be reused/needed later public int release() { int state = this.atomicState.addAndGet(-2); - if (state < 1) { - throw new IllegalStateException("Section got into an invalid state"); - } - if ((state&1)==0) { - throw new IllegalStateException("Tried releasing a freed section"); + if (VERIFY_WORLD_SECTION_EXECUTION) { + if (state < 1) { + throw new IllegalStateException("Section got into an invalid state"); + } + if ((state & 1) == 0) { + throw new IllegalStateException("Tried releasing a freed section"); + } } if ((state>>1)==0) { this.tracker.tryUnload(this); } - return state>>1; } //Returns true on success, false on failure boolean trySetFreed() { int witness = this.atomicState.compareAndExchange(1, 0); - if ((witness&1)==0 && witness != 0) { - throw new IllegalStateException("Section marked as free but has refs"); + if (VERIFY_WORLD_SECTION_EXECUTION) { + if ((witness & 1) == 0 && witness != 0) { + throw new IllegalStateException("Section marked as free but has refs"); + } } boolean isFreed = witness == 1; if (isFreed) { @@ -106,15 +123,19 @@ public final class WorldSection { } public void assertNotFree() { - if ((this.atomicState.get() & 1) == 0) { - throw new IllegalStateException(); + if (VERIFY_WORLD_SECTION_EXECUTION) { + if ((this.atomicState.get() & 1) == 0) { + throw new IllegalStateException(); + } } } public static int getIndex(int x, int y, int z) { int M = (1<<5)-1; - if (x<0||x>M||y<0||y>M||z<0||z>M) { - throw new IllegalArgumentException("Out of bounds: " + x + ", " + y + ", " + z); + if (VERIFY_WORLD_SECTION_EXECUTION) { + if (x < 0 || x > M || y < 0 || y > M || z < 0 || z > M) { + throw new IllegalArgumentException("Out of bounds: " + x + ", " + y + ", " + z); + } } return ((y&M)<<10)|((z&M)<<5)|(x&M); } @@ -137,16 +158,6 @@ public final class WorldSection { if (cache.length != this.data.length) throw new IllegalArgumentException(); System.arraycopy(this.data, 0, cache, 0, this.data.length); } - - public boolean tryAcquire() { - int state = this.atomicState.updateAndGet(val -> { - if ((val&1) != 0) { - return val+2; - } - return val; - }); - return (state&1) != 0; - } } //TODO: for serialization, make a huffman encoding tree on the integers since that should be very very efficent for compression