mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-02-16 02:20:57 +00:00
Improve TriStateintCache with Unsafe
This commit is contained in:
@@ -33,8 +33,7 @@ public class ReplaceExtrusion implements Extrusion {
|
||||
this.range = range;
|
||||
this.biomes = biomes;
|
||||
this.hasTag = BiomeQueries.has(tag);
|
||||
|
||||
this.cache = new TriStateIntCache(65536);
|
||||
this.cache = new TriStateIntCache(Math.max(512, Biome.INT_ID_COUNTER.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.dfsek.terra.api.world.biome.PlatformBiome;
|
||||
* Class representing a config-defined biome
|
||||
*/
|
||||
public class UserDefinedBiome implements Biome {
|
||||
private final static AtomicInteger INT_ID_COUNTER = new AtomicInteger(0);
|
||||
private final PlatformBiome vanilla;
|
||||
private final String id;
|
||||
private final BiomeTemplate config;
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package com.dfsek.terra.api.util.collection;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLongArray;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import com.dfsek.seismic.util.UnsafeUtils;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
public class TriStateIntCache {
|
||||
public static final long STATE_UNSET = 0L;
|
||||
@@ -9,10 +13,19 @@ public class TriStateIntCache {
|
||||
public static final long STATE_TRUE = 2L;
|
||||
|
||||
private static final long BIT_MASK = 3L;
|
||||
private final AtomicLongArray data;
|
||||
private final long[] data;
|
||||
|
||||
private static final VarHandle ARRAY_HANDLE = MethodHandles.arrayElementVarHandle(long[].class);
|
||||
|
||||
private static final long ARRAY_BASE_OFFSET;
|
||||
|
||||
static {
|
||||
assert UnsafeUtils.UNSAFE != null;
|
||||
ARRAY_BASE_OFFSET = UnsafeUtils.UNSAFE.arrayBaseOffset(long[].class);
|
||||
}
|
||||
|
||||
public TriStateIntCache(int maxKeySize) {
|
||||
this.data = new AtomicLongArray((maxKeySize + 31) >>> 5);
|
||||
this.data = new long[(maxKeySize + 31) >>> 5];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21,33 +34,28 @@ public class TriStateIntCache {
|
||||
* @return STATE_UNSET (0), STATE_FALSE (1), or STATE_TRUE (2)
|
||||
*/
|
||||
public long get(int key) {
|
||||
int arrayIndex = key >>> 5;
|
||||
int bitShift = (key & 31) << 1;
|
||||
long currentWord = data.get(arrayIndex);
|
||||
return (currentWord >>> bitShift) & BIT_MASK;
|
||||
long offset = ARRAY_BASE_OFFSET + ((long)(key >>> 5) << 3);
|
||||
long currentWord = UnsafeUtils.UNSAFE.getLong(data, offset);
|
||||
return (currentWord >>> ((key << 1) & 63)) & BIT_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value safely. Handles race conditions internally.
|
||||
*/
|
||||
public void set(int key, boolean value) {
|
||||
int arrayIndex = key >>> 5;
|
||||
int bitShift = (key & 31) << 1;
|
||||
long targetState = value ? STATE_TRUE : STATE_FALSE;
|
||||
int index = key >>> 5;
|
||||
int shift = (key << 1) & 63;
|
||||
|
||||
long currentWord, newWord;
|
||||
long targetWord = (value ? STATE_TRUE : STATE_FALSE) << shift;
|
||||
|
||||
long current;
|
||||
do {
|
||||
currentWord = data.get(arrayIndex);
|
||||
current = (long) ARRAY_HANDLE.getVolatile(data, index);
|
||||
|
||||
// Race condition check:
|
||||
long existingState = (currentWord >>> bitShift) & BIT_MASK;
|
||||
if(existingState != STATE_UNSET) {
|
||||
return; // Already set, abort our update
|
||||
if (((current >>> shift) & BIT_MASK) != STATE_UNSET) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new word with our bit set
|
||||
newWord = (currentWord & ~(BIT_MASK << bitShift)) | (targetState << bitShift);
|
||||
|
||||
} while(!data.compareAndSet(arrayIndex, currentWord, newWord));
|
||||
} while (!ARRAY_HANDLE.compareAndSet(data, index, current, current | targetWord));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ package com.dfsek.terra.api.world.biome;
|
||||
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.dfsek.terra.api.properties.PropertyHolder;
|
||||
import com.dfsek.terra.api.registry.key.StringIdentifiable;
|
||||
@@ -18,6 +19,7 @@ import com.dfsek.terra.api.registry.key.StringIdentifiable;
|
||||
* Represents a Terra biome
|
||||
*/
|
||||
public interface Biome extends PropertyHolder, StringIdentifiable {
|
||||
AtomicInteger INT_ID_COUNTER = new AtomicInteger(0);
|
||||
|
||||
/**
|
||||
* Gets the platform biome this custom biome delegates to.
|
||||
|
||||
Reference in New Issue
Block a user