stamps and notes
This commit is contained in:
@@ -4,18 +4,21 @@ import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap;
|
|||||||
import me.cortex.voxy.common.world.WorldEngine;
|
import me.cortex.voxy.common.world.WorldEngine;
|
||||||
import me.cortex.voxy.common.world.WorldSection;
|
import me.cortex.voxy.common.world.WorldSection;
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.StampedLock;
|
||||||
import java.util.function.LongConsumer;
|
import java.util.function.LongConsumer;
|
||||||
|
|
||||||
import static me.cortex.voxy.common.world.WorldEngine.UPDATE_TYPE_BLOCK_BIT;
|
import static me.cortex.voxy.common.world.WorldEngine.UPDATE_TYPE_BLOCK_BIT;
|
||||||
|
|
||||||
public class SectionUpdateRouter implements ISectionWatcher {
|
public class SectionUpdateRouter implements ISectionWatcher {
|
||||||
private static final int SLICES = 1<<8;
|
private static final int SLICES = 1<<4;
|
||||||
public interface IChildUpdate {void accept(WorldSection section);}
|
public interface IChildUpdate {void accept(WorldSection section);}
|
||||||
|
|
||||||
private final Long2ByteOpenHashMap[] slices = new Long2ByteOpenHashMap[SLICES];
|
private final Long2ByteOpenHashMap[] slices = new Long2ByteOpenHashMap[SLICES];
|
||||||
|
private final StampedLock[] locks = new StampedLock[SLICES];
|
||||||
{
|
{
|
||||||
for (int i = 0; i < this.slices.length; i++) {
|
for (int i = 0; i < this.slices.length; i++) {
|
||||||
this.slices[i] = new Long2ByteOpenHashMap();
|
this.slices[i] = new Long2ByteOpenHashMap();
|
||||||
|
this.locks[i] = new StampedLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,17 +38,34 @@ public class SectionUpdateRouter implements ISectionWatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean watch(long position, int types) {
|
public boolean watch(long position, int types) {
|
||||||
var set = this.slices[getSliceIndex(position)];
|
int idx = getSliceIndex(position);
|
||||||
|
var set = this.slices[idx];
|
||||||
|
var lock = this.locks[idx];
|
||||||
byte delta = 0;
|
byte delta = 0;
|
||||||
synchronized (set) {
|
{
|
||||||
byte current = 0;
|
long stamp = lock.readLock();
|
||||||
if (set.containsKey(position)) {
|
byte current = set.getOrDefault(position, (byte) 0);
|
||||||
current = set.get(position);
|
|
||||||
}
|
|
||||||
delta = (byte) (current&types);
|
delta = (byte) (current&types);
|
||||||
current |= (byte) types;
|
current |= (byte) types;
|
||||||
delta ^= (byte) (current&types);
|
delta ^= (byte) (current&types);
|
||||||
set.put(position, current);
|
if (delta != 0) {//Was change
|
||||||
|
long ws = lock.tryConvertToWriteLock(stamp);
|
||||||
|
if (ws == 0) {
|
||||||
|
lock.unlockRead(stamp);
|
||||||
|
stamp = lock.writeLock();
|
||||||
|
//We need to recompute as we failed to acquire an immediate write lock
|
||||||
|
current = set.getOrDefault(position, (byte) 0);
|
||||||
|
delta = (byte) (current&types);
|
||||||
|
current |= (byte) types;
|
||||||
|
delta ^= (byte) (current&types);
|
||||||
|
if (delta != 0)
|
||||||
|
set.put(position, current);
|
||||||
|
} else {
|
||||||
|
stamp = ws;
|
||||||
|
set.put(position, current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lock.unlock(stamp);
|
||||||
}
|
}
|
||||||
if ((delta&UPDATE_TYPE_BLOCK_BIT)!=0) {
|
if ((delta&UPDATE_TYPE_BLOCK_BIT)!=0) {
|
||||||
//If we added it, immediately invoke for an update
|
//If we added it, immediately invoke for an update
|
||||||
@@ -58,38 +78,67 @@ public class SectionUpdateRouter implements ISectionWatcher {
|
|||||||
return this.unwatch(WorldEngine.getWorldSectionId(lvl, x, y, z), types);
|
return this.unwatch(WorldEngine.getWorldSectionId(lvl, x, y, z), types);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean unwatch(long position, int types) {
|
public boolean unwatch(long position, int types) {//Types is types to unwatch
|
||||||
var set = this.slices[getSliceIndex(position)];
|
int idx = getSliceIndex(position);
|
||||||
synchronized (set) {
|
var set = this.slices[idx];
|
||||||
if (!set.containsKey(position)) {
|
var lock = this.locks[idx];
|
||||||
throw new IllegalStateException("Section pos not in map!! " + WorldEngine.pprintPos(position));
|
|
||||||
}
|
long stamp = lock.readLock();
|
||||||
byte current = set.get(position);
|
|
||||||
byte delta = (byte) (current&types);
|
byte current = set.getOrDefault(position, (byte)0);
|
||||||
current &= (byte) ~types;
|
if (current == 0) {
|
||||||
if (current == 0) {
|
throw new IllegalStateException("Section pos not in map " + WorldEngine.pprintPos(position));
|
||||||
set.remove(position);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
set.put(position, current);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
boolean removed = false;
|
||||||
|
if ((current&types) != 0) {//Was change
|
||||||
|
long ws = lock.tryConvertToWriteLock(stamp);
|
||||||
|
if (ws == 0) {//failed to get write lock, need to unlock, get write, then redo
|
||||||
|
lock.unlockRead(stamp);
|
||||||
|
stamp = lock.writeLock();
|
||||||
|
|
||||||
|
current = set.getOrDefault(position, (byte)0);
|
||||||
|
if (current == 0) {
|
||||||
|
throw new IllegalStateException("Section pos not in map " + WorldEngine.pprintPos(position));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stamp = ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((current&types) != 0) {
|
||||||
|
current &= (byte) ~types;
|
||||||
|
if (current == 0) {
|
||||||
|
set.remove(position);
|
||||||
|
removed = true;
|
||||||
|
} else {
|
||||||
|
set.put(position, current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lock.unlock(stamp);
|
||||||
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int get(long position) {
|
public int get(long position) {
|
||||||
var set = this.slices[getSliceIndex(position)];
|
int idx = getSliceIndex(position);
|
||||||
synchronized (set) {
|
var set = this.slices[idx];
|
||||||
return set.getOrDefault(position, (byte) 0);
|
var lock = this.locks[idx];
|
||||||
}
|
long stamp = lock.readLock();
|
||||||
|
int ret = set.getOrDefault(position, (byte) 0);
|
||||||
|
lock.unlockRead(stamp);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forwardEvent(WorldSection section, int type) {
|
public void forwardEvent(WorldSection section, int type) {
|
||||||
final long position = section.key;
|
final long position = section.key;
|
||||||
var set = this.slices[getSliceIndex(position)];
|
|
||||||
byte types = 0;
|
int idx = getSliceIndex(position);
|
||||||
synchronized (set) {
|
var set = this.slices[idx];
|
||||||
types = set.getOrDefault(position, (byte)0);
|
var lock = this.locks[idx];
|
||||||
}
|
|
||||||
|
long stamp = lock.readLock();
|
||||||
|
byte types = set.getOrDefault(position, (byte) 0);
|
||||||
|
lock.unlockRead(stamp);
|
||||||
|
|
||||||
if (types!=0) {
|
if (types!=0) {
|
||||||
if ((type&WorldEngine.UPDATE_TYPE_CHILD_EXISTENCE_BIT)!=0) {
|
if ((type&WorldEngine.UPDATE_TYPE_CHILD_EXISTENCE_BIT)!=0) {
|
||||||
this.childUpdateCallback.accept(section);
|
this.childUpdateCallback.accept(section);
|
||||||
|
|||||||
@@ -331,6 +331,7 @@ public class RenderDataFactory45 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: add neighbor face culling
|
||||||
private void generateYZOpaqueInnerGeometry(int axis) {
|
private void generateYZOpaqueInnerGeometry(int axis) {
|
||||||
for (int layer = 0; layer < 31; layer++) {
|
for (int layer = 0; layer < 31; layer++) {
|
||||||
this.blockMesher.auxiliaryPosition = layer;
|
this.blockMesher.auxiliaryPosition = layer;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import org.lwjgl.system.MemoryUtil;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.function.LongConsumer;
|
import java.util.function.LongConsumer;
|
||||||
|
|
||||||
|
//TODO: replace synchronize with StampedLock
|
||||||
public class MemoryStorageBackend extends StorageBackend {
|
public class MemoryStorageBackend extends StorageBackend {
|
||||||
private final Long2ObjectMap<MemoryBuffer>[] maps;
|
private final Long2ObjectMap<MemoryBuffer>[] maps;
|
||||||
private final Int2ObjectMap<ByteBuffer> idMappings = new Int2ObjectOpenHashMap<>();
|
private final Int2ObjectMap<ByteBuffer> idMappings = new Int2ObjectOpenHashMap<>();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class ActiveSectionTracker {
|
|||||||
//Loaded section world cache, TODO: get rid of VolatileHolder and use something more sane
|
//Loaded section world cache, TODO: get rid of VolatileHolder and use something more sane
|
||||||
|
|
||||||
private final Long2ObjectOpenHashMap<VolatileHolder<WorldSection>>[] loadedSectionCache;
|
private final Long2ObjectOpenHashMap<VolatileHolder<WorldSection>>[] loadedSectionCache;
|
||||||
private final ReentrantLock[] locks;
|
private final ReentrantLock[] locks;//TODO: replace with StampedLocks
|
||||||
private final SectionLoader loader;
|
private final SectionLoader loader;
|
||||||
|
|
||||||
private final int lruSize;
|
private final int lruSize;
|
||||||
|
|||||||
Reference in New Issue
Block a user