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