remove concurrent datastructures
Some checks reported errors
studiorailgun/Renderer/pipeline/head Something is wrong with the build of this commit

This commit is contained in:
austin 2024-11-29 21:36:05 -05:00
parent dfc59e0ea6
commit 0f85b0ac92
7 changed files with 64 additions and 27 deletions

View File

@ -13,6 +13,7 @@ TODO(?):
- Network optimization - Network optimization
- Building cube voxels w/ LOD - Building cube voxels w/ LOD
- Tools to build voxels
- Audio Ray Tracing - Audio Ray Tracing

View File

@ -1189,6 +1189,7 @@ Spawn characters from database
Fluid spawning item Fluid spawning item
Fix fluid shader Fix fluid shader
Re-enable fluid simulation Re-enable fluid simulation
Remove concurrent datastructure usage in cell management
# TODO # TODO

View File

@ -6,7 +6,6 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import io.github.studiorailgun.HashUtils; import io.github.studiorailgun.HashUtils;
@ -29,27 +28,27 @@ public class BlockChunkCache {
/** /**
* The map of full res chunk key -> chunk data * The map of full res chunk key -> chunk data
*/ */
Map<Long,BlockChunkData> cacheMapFullRes = new ConcurrentHashMap<Long,BlockChunkData>(); Map<Long,BlockChunkData> cacheMapFullRes = new HashMap<Long,BlockChunkData>();
/** /**
* The map of half res chunk key -> chunk data * The map of half res chunk key -> chunk data
*/ */
Map<Long,BlockChunkData> cacheMapHalfRes = new ConcurrentHashMap<Long,BlockChunkData>(); Map<Long,BlockChunkData> cacheMapHalfRes = new HashMap<Long,BlockChunkData>();
/** /**
* The map of quarter res chunk key -> chunk data * The map of quarter res chunk key -> chunk data
*/ */
Map<Long,BlockChunkData> cacheMapQuarterRes = new ConcurrentHashMap<Long,BlockChunkData>(); Map<Long,BlockChunkData> cacheMapQuarterRes = new HashMap<Long,BlockChunkData>();
/** /**
* The map of eighth res chunk key -> chunk data * The map of eighth res chunk key -> chunk data
*/ */
Map<Long,BlockChunkData> cacheMapEighthRes = new ConcurrentHashMap<Long,BlockChunkData>(); Map<Long,BlockChunkData> cacheMapEighthRes = new HashMap<Long,BlockChunkData>();
/** /**
* The map of sixteenth res chunk key -> chunk data * The map of sixteenth res chunk key -> chunk data
*/ */
Map<Long,BlockChunkData> cacheMapSixteenthRes = new ConcurrentHashMap<Long,BlockChunkData>(); Map<Long,BlockChunkData> cacheMapSixteenthRes = new HashMap<Long,BlockChunkData>();
/** /**
* Tracks how recently a chunk has been queries for (used for evicting old chunks from cache) * Tracks how recently a chunk has been queries for (used for evicting old chunks from cache)

View File

@ -1,9 +1,9 @@
package electrosphere.client.fluid.cache; package electrosphere.client.fluid.cache;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/** /**
@ -14,9 +14,9 @@ public class ClientFluidCache {
//cache capacity //cache capacity
int cacheSize; int cacheSize;
//the map of chunk key -> chunk data //the map of chunk key -> chunk data
Map<String,FluidChunkData> cacheMap = new ConcurrentHashMap<String,FluidChunkData>(); Map<String,FluidChunkData> cacheMap = new HashMap<String,FluidChunkData>();
//the list of keys in the cache //the list of keys in the cache
List<String> cacheList = new CopyOnWriteArrayList<String>(); List<String> cacheList = new LinkedList<String>();
/** /**
* Constructor * Constructor

View File

@ -5,7 +5,7 @@ import java.nio.FloatBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.ReentrantLock;
import org.joml.Vector3i; import org.joml.Vector3i;
@ -27,7 +27,7 @@ import electrosphere.server.terrain.manager.ServerTerrainManager;
public class ClientFluidManager { public class ClientFluidManager {
//queues messages from server //queues messages from server
List<TerrainMessage> messageQueue = new CopyOnWriteArrayList<TerrainMessage>(); List<TerrainMessage> messageQueue = new LinkedList<TerrainMessage>();
//The interpolation ratio of fluid //The interpolation ratio of fluid
public static final int INTERPOLATION_RATIO = ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO; public static final int INTERPOLATION_RATIO = ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO;
@ -42,7 +42,12 @@ public class ClientFluidManager {
ClientWorldData clientWorldData; ClientWorldData clientWorldData;
//The queue of fluid chunk data to be buffered to gpu //The queue of fluid chunk data to be buffered to gpu
static List<FluidChunkGenQueueItem> fluidChunkGenerationQueue = new CopyOnWriteArrayList<FluidChunkGenQueueItem>(); static List<FluidChunkGenQueueItem> fluidChunkGenerationQueue = new LinkedList<FluidChunkGenQueueItem>();
/**
* Lock for thread-safeing the manager
*/
static ReentrantLock lock = new ReentrantLock();
/** /**
* Constructor * Constructor
@ -53,9 +58,9 @@ public class ClientFluidManager {
public void handleMessages(){ public void handleMessages(){
lock.lock();
List<TerrainMessage> bouncedMessages = new LinkedList<TerrainMessage>(); List<TerrainMessage> bouncedMessages = new LinkedList<TerrainMessage>();
for(TerrainMessage message : messageQueue){ for(TerrainMessage message : messageQueue){
messageQueue.remove(message);
switch(message.getMessageSubtype()){ switch(message.getMessageSubtype()){
case SENDFLUIDDATA: { case SENDFLUIDDATA: {
ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData()); ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
@ -81,13 +86,17 @@ public class ClientFluidManager {
break; break;
} }
} }
messageQueue.clear();
for(TerrainMessage message : bouncedMessages){ for(TerrainMessage message : bouncedMessages){
messageQueue.add(message); messageQueue.add(message);
} }
lock.unlock();
} }
public void attachFluidMessage(TerrainMessage message){ public void attachFluidMessage(TerrainMessage message){
lock.lock();
messageQueue.add(message); messageQueue.add(message);
lock.unlock();
} }
public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){ public boolean containsChunkDataAtWorldPoint(int worldX, int worldY, int worldZ){
@ -135,7 +144,9 @@ public class ClientFluidManager {
UUID newUUID = UUID.randomUUID(); UUID newUUID = UUID.randomUUID();
promisedHash = newUUID.toString(); promisedHash = newUUID.toString();
FluidChunkGenQueueItem queueItem = new FluidChunkGenQueueItem(data, promisedHash); FluidChunkGenQueueItem queueItem = new FluidChunkGenQueueItem(data, promisedHash);
lock.lock();
fluidChunkGenerationQueue.add(queueItem); fluidChunkGenerationQueue.add(queueItem);
lock.unlock();
return promisedHash; return promisedHash;
} }
@ -144,11 +155,13 @@ public class ClientFluidManager {
*/ */
public static void generateFluidChunkGeometry(){ public static void generateFluidChunkGeometry(){
Globals.profiler.beginCpuSample("generateFluidChunkGeometry"); Globals.profiler.beginCpuSample("generateFluidChunkGeometry");
lock.lock();
for(FluidChunkGenQueueItem queueItem : fluidChunkGenerationQueue){ for(FluidChunkGenQueueItem queueItem : fluidChunkGenerationQueue){
Model fluidModel = FluidChunkModelGeneration.generateFluidModel(queueItem.getData()); Model fluidModel = FluidChunkModelGeneration.generateFluidModel(queueItem.getData());
Globals.assetManager.registerModelToSpecificString(fluidModel, queueItem.getPromisedHash()); Globals.assetManager.registerModelToSpecificString(fluidModel, queueItem.getPromisedHash());
} }
fluidChunkGenerationQueue.clear(); fluidChunkGenerationQueue.clear();
lock.unlock();
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
} }

View File

@ -11,12 +11,15 @@ import electrosphere.server.fluid.simulator.cellularautomata.FluidCellularAutoma
import electrosphere.server.terrain.manager.ServerTerrainChunk; import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.server.terrain.manager.ServerTerrainManager; import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.util.FileUtils; import electrosphere.util.FileUtils;
import electrosphere.util.annotation.Exclude;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.CopyOnWriteArrayList;
import org.joml.Vector3i; import org.joml.Vector3i;
@ -37,28 +40,40 @@ public class ServerFluidManager {
//While we incur a penalty with converting ints -> string, think this will //While we incur a penalty with converting ints -> string, think this will
//offset regenerating the array every time we want a new one //offset regenerating the array every time we want a new one
int cacheSize = 500; int cacheSize = 500;
@Exclude
Map<String, ServerFluidChunk> chunkCache; Map<String, ServerFluidChunk> chunkCache;
@Exclude
List<String> chunkCacheContents; List<String> chunkCacheContents;
//The map of chunk position <-> file on disk containing chunk data //The map of chunk position <-> file on disk containing chunk data
FluidDiskMap chunkDiskMap = null; FluidDiskMap chunkDiskMap = null;
@Exclude
//The generation algorithm for this fluid manager //The generation algorithm for this fluid manager
FluidGenerator chunkGenerator; FluidGenerator chunkGenerator;
@Exclude
//the fluid simulator //the fluid simulator
ServerFluidSimulator serverFluidSimulator; ServerFluidSimulator serverFluidSimulator;
@Exclude
//the terrain manager associated //the terrain manager associated
ServerTerrainManager serverTerrainManager; ServerTerrainManager serverTerrainManager;
//controls whether fluid simulation should actually happen or not //controls whether fluid simulation should actually happen or not
boolean simulate = false; boolean simulate = false;
@Exclude
/** /**
* The parent world data * The parent world data
*/ */
ServerWorldData parent; ServerWorldData parent;
@Exclude
/**
* Locks the fluid manager
*/
ReentrantLock lock = new ReentrantLock();
/** /**
@ -72,8 +87,8 @@ public class ServerFluidManager {
){ ){
this.parent = parent; this.parent = parent;
this.serverTerrainManager = serverTerrainManager; this.serverTerrainManager = serverTerrainManager;
this.chunkCache = new ConcurrentHashMap<String, ServerFluidChunk>(); this.chunkCache = new HashMap<String, ServerFluidChunk>();
this.chunkCacheContents = new CopyOnWriteArrayList<String>(); this.chunkCacheContents = new LinkedList<String>();
this.seed = seed; this.seed = seed;
this.chunkGenerator = chunkGenerator; this.chunkGenerator = chunkGenerator;
this.serverFluidSimulator = new FluidCellularAutomataSimulator(); this.serverFluidSimulator = new FluidCellularAutomataSimulator();
@ -94,6 +109,7 @@ public class ServerFluidManager {
* @param saveName The name of the save * @param saveName The name of the save
*/ */
public void save(String saveName){ public void save(String saveName){
lock.lock();
if(model != null){ if(model != null){
ByteBuffer buffer = ByteBuffer.allocate(model.getElevation().length * model.getElevation()[0].length * 4); ByteBuffer buffer = ByteBuffer.allocate(model.getElevation().length * model.getElevation()[0].length * 4);
FloatBuffer floatView = buffer.asFloatBuffer(); FloatBuffer floatView = buffer.asFloatBuffer();
@ -115,6 +131,7 @@ public class ServerFluidManager {
if(chunkDiskMap != null){ if(chunkDiskMap != null){
chunkDiskMap.save(); chunkDiskMap.save();
} }
lock.unlock();
} }
/** /**
@ -203,14 +220,14 @@ public class ServerFluidManager {
* @return The ServerFluidChunk * @return The ServerFluidChunk
*/ */
public ServerFluidChunk getChunk(int worldX, int worldY, int worldZ){ public ServerFluidChunk getChunk(int worldX, int worldY, int worldZ){
ServerFluidChunk returnedChunk = null;
lock.lock();
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING //THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
String key = getKey(worldX,worldY,worldZ); String key = getKey(worldX,worldY,worldZ);
ServerFluidChunk returnedChunk = null;
if(chunkCache.containsKey(key)){ if(chunkCache.containsKey(key)){
chunkCacheContents.remove(key); chunkCacheContents.remove(key);
chunkCacheContents.add(0, key); chunkCacheContents.add(0, key);
returnedChunk = chunkCache.get(key); returnedChunk = chunkCache.get(key);
return returnedChunk;
} else { } else {
if(chunkCacheContents.size() > cacheSize){ if(chunkCacheContents.size() > cacheSize){
String oldChunk = chunkCacheContents.remove(chunkCacheContents.size() - 1); String oldChunk = chunkCacheContents.remove(chunkCacheContents.size() - 1);
@ -228,8 +245,9 @@ public class ServerFluidManager {
} }
chunkCache.put(key, returnedChunk); chunkCache.put(key, returnedChunk);
chunkCacheContents.add(key); chunkCacheContents.add(key);
return returnedChunk;
} }
lock.unlock();
return returnedChunk;
} }
/** /**
@ -238,7 +256,9 @@ public class ServerFluidManager {
* @param position The position to save * @param position The position to save
*/ */
public void savePositionToDisk(Vector3i position){ public void savePositionToDisk(Vector3i position){
lock.lock();
chunkDiskMap.saveToDisk(getChunk(position.x, position.y, position.z)); chunkDiskMap.saveToDisk(getChunk(position.x, position.y, position.z));
lock.unlock();
} }
/** /**
@ -259,8 +279,10 @@ public class ServerFluidManager {
// ServerFluidChunk chunk = chunkCache.get(key); // ServerFluidChunk chunk = chunkCache.get(key);
// chunk.addModification(modification); // chunk.addModification(modification);
// } // }
lock.lock();
ServerFluidChunk fluidChunk = this.getChunk(worldPos.x, worldPos.y, worldPos.z); ServerFluidChunk fluidChunk = this.getChunk(worldPos.x, worldPos.y, worldPos.z);
fluidChunk.setWeight(voxelPos.x, voxelPos.y, voxelPos.z, weight); fluidChunk.setWeight(voxelPos.x, voxelPos.y, voxelPos.z, weight);
lock.unlock();
} }
/** /**
@ -269,6 +291,7 @@ public class ServerFluidManager {
public boolean simulate(int worldX, int worldY, int worldZ){ public boolean simulate(int worldX, int worldY, int worldZ){
boolean rVal = false; boolean rVal = false;
Globals.profiler.beginAggregateCpuSample("ServerFluidManager.simulate"); Globals.profiler.beginAggregateCpuSample("ServerFluidManager.simulate");
lock.lock();
if(simulate){ if(simulate){
ServerFluidChunk fluidChunk = this.getChunk(worldX, worldY, worldZ); ServerFluidChunk fluidChunk = this.getChunk(worldX, worldY, worldZ);
ServerTerrainChunk terrainChunk = this.serverTerrainManager.getChunk(worldX, worldY, worldZ); ServerTerrainChunk terrainChunk = this.serverTerrainManager.getChunk(worldX, worldY, worldZ);
@ -276,6 +299,7 @@ public class ServerFluidManager {
rVal = this.serverFluidSimulator.simulate(fluidChunk,terrainChunk,worldX,worldY,worldZ); rVal = this.serverFluidSimulator.simulate(fluidChunk,terrainChunk,worldX,worldY,worldZ);
} }
} }
lock.unlock();
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
return rVal; return rVal;
} }

View File

@ -6,7 +6,6 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import io.github.studiorailgun.HashUtils; import io.github.studiorailgun.HashUtils;
@ -29,27 +28,27 @@ public class ServerChunkCache {
/** /**
* The map of full res chunk key -> chunk data * The map of full res chunk key -> chunk data
*/ */
Map<Long,ServerTerrainChunk> cacheMapFullRes = new ConcurrentHashMap<Long,ServerTerrainChunk>(); Map<Long,ServerTerrainChunk> cacheMapFullRes = new HashMap<Long,ServerTerrainChunk>();
/** /**
* The map of half res chunk key -> chunk data * The map of half res chunk key -> chunk data
*/ */
Map<Long,ServerTerrainChunk> cacheMapHalfRes = new ConcurrentHashMap<Long,ServerTerrainChunk>(); Map<Long,ServerTerrainChunk> cacheMapHalfRes = new HashMap<Long,ServerTerrainChunk>();
/** /**
* The map of quarter res chunk key -> chunk data * The map of quarter res chunk key -> chunk data
*/ */
Map<Long,ServerTerrainChunk> cacheMapQuarterRes = new ConcurrentHashMap<Long,ServerTerrainChunk>(); Map<Long,ServerTerrainChunk> cacheMapQuarterRes = new HashMap<Long,ServerTerrainChunk>();
/** /**
* The map of eighth res chunk key -> chunk data * The map of eighth res chunk key -> chunk data
*/ */
Map<Long,ServerTerrainChunk> cacheMapEighthRes = new ConcurrentHashMap<Long,ServerTerrainChunk>(); Map<Long,ServerTerrainChunk> cacheMapEighthRes = new HashMap<Long,ServerTerrainChunk>();
/** /**
* The map of sixteenth res chunk key -> chunk data * The map of sixteenth res chunk key -> chunk data
*/ */
Map<Long,ServerTerrainChunk> cacheMapSixteenthRes = new ConcurrentHashMap<Long,ServerTerrainChunk>(); Map<Long,ServerTerrainChunk> cacheMapSixteenthRes = new HashMap<Long,ServerTerrainChunk>();
/** /**
* Tracks how recently a chunk has been queries for (used for evicting old chunks from cache) * Tracks how recently a chunk has been queries for (used for evicting old chunks from cache)