safe executor service creation
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				studiorailgun/Renderer/pipeline/head There was a failure building this commit
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	studiorailgun/Renderer/pipeline/head There was a failure building this commit
				
			This commit is contained in:
		
							parent
							
								
									c6948b89ce
								
							
						
					
					
						commit
						7ad7a0c477
					
				| @ -1796,6 +1796,7 @@ Support for freeing shaders | |||||||
| Utilities to free all of a type of resource | Utilities to free all of a type of resource | ||||||
| Slowdown entity tests to prevent VSCode from exploding when running tests | Slowdown entity tests to prevent VSCode from exploding when running tests | ||||||
| Fix static state caching between tests in visual shader construction | Fix static state caching between tests in visual shader construction | ||||||
|  | Safe executor service creation in non final static contexts | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -39,6 +39,22 @@ public class ImGuiRenderer { | |||||||
|                     } |                     } | ||||||
|                     ImGui.unindent(); |                     ImGui.unindent(); | ||||||
|                 } |                 } | ||||||
|  |                 if(ImGui.collapsingHeader("Debug Toggles")){ | ||||||
|  |                     ImGui.indent(); | ||||||
|  |                     if(ImGui.button("Draw Client Hitboxes")){ | ||||||
|  |                         Globals.userSettings.setGraphicsDebugDrawCollisionSpheresClient(!Globals.userSettings.getGraphicsDebugDrawCollisionSpheresClient()); | ||||||
|  |                     } | ||||||
|  |                     if(ImGui.button("Draw Server Hitboxes")){ | ||||||
|  |                         Globals.userSettings.setGraphicsDebugDrawCollisionSpheresServer(!Globals.userSettings.getGraphicsDebugDrawCollisionSpheresServer()); | ||||||
|  |                     } | ||||||
|  |                     if(ImGui.button("Draw Physics Objects")){ | ||||||
|  |                         Globals.userSettings.setGraphicsDebugDrawPhysicsObjects(!Globals.userSettings.graphicsDebugDrawPhysicsObjects()); | ||||||
|  |                     } | ||||||
|  |                     if(ImGui.button("Draw Grid Alignment Data")){ | ||||||
|  |                         Globals.userSettings.setGraphicsDebugDrawGridAlignment(!Globals.userSettings.getGraphicsDebugDrawGridAlignment()); | ||||||
|  |                     } | ||||||
|  |                     ImGui.unindent(); | ||||||
|  |                 } | ||||||
|                 if(ImGui.collapsingHeader("OpenGL Details")){ |                 if(ImGui.collapsingHeader("OpenGL Details")){ | ||||||
|                     ImGui.text("GL_MAX_TEXTURE_IMAGE_UNITS: " + Globals.renderingEngine.getOpenGLContext().getMaxTextureImageUnits()); |                     ImGui.text("GL_MAX_TEXTURE_IMAGE_UNITS: " + Globals.renderingEngine.getOpenGLContext().getMaxTextureImageUnits()); | ||||||
|                     ImGui.text("GL_MAX_TEXTURE_SIZE: " + Globals.renderingEngine.getOpenGLContext().getMaxTextureSize()); |                     ImGui.text("GL_MAX_TEXTURE_SIZE: " + Globals.renderingEngine.getOpenGLContext().getMaxTextureSize()); | ||||||
|  | |||||||
| @ -3,8 +3,10 @@ package electrosphere.engine.threads; | |||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.LinkedList; | import java.util.LinkedList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.concurrent.Semaphore; | import java.util.concurrent.ExecutorService; | ||||||
|  | import java.util.concurrent.Executors; | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
|  | import java.util.concurrent.locks.ReentrantLock; | ||||||
| 
 | 
 | ||||||
| import electrosphere.client.terrain.foliage.FoliageModel; | import electrosphere.client.terrain.foliage.FoliageModel; | ||||||
| import electrosphere.engine.Globals; | import electrosphere.engine.Globals; | ||||||
| @ -13,7 +15,6 @@ import electrosphere.engine.threads.LabeledThread.ThreadLabel; | |||||||
| import electrosphere.entity.types.terrain.BlockChunkEntity; | import electrosphere.entity.types.terrain.BlockChunkEntity; | ||||||
| import electrosphere.entity.types.terrain.TerrainChunk; | import electrosphere.entity.types.terrain.TerrainChunk; | ||||||
| import electrosphere.server.ai.services.PathfindingService; | import electrosphere.server.ai.services.PathfindingService; | ||||||
| import electrosphere.server.datacell.gridded.GriddedDataCellLoaderService; |  | ||||||
| import electrosphere.util.CodeUtils; | import electrosphere.util.CodeUtils; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -21,24 +22,37 @@ import electrosphere.util.CodeUtils; | |||||||
|  */ |  */ | ||||||
| public class ThreadManager { | public class ThreadManager { | ||||||
|      |      | ||||||
|     //Threadsafes the manager |     /** | ||||||
|     Semaphore threadLock; |      * Threadsafes the manager | ||||||
|  |      */ | ||||||
|  |     private ReentrantLock threadLock; | ||||||
| 
 | 
 | ||||||
|     //All threads that are actively running |     /** | ||||||
|  |      * All threads that are actively running | ||||||
|  |      */ | ||||||
|     private List<LabeledThread> activeThreads; |     private List<LabeledThread> activeThreads; | ||||||
| 
 | 
 | ||||||
|     //All loading threads that are actively running |     /** | ||||||
|  |      * All loading threads that are actively running | ||||||
|  |      */ | ||||||
|     private List<LoadingThread> loadingThreads; |     private List<LoadingThread> loadingThreads; | ||||||
| 
 | 
 | ||||||
|     //Used by main thread to alert other threads whether they should keep running or not |     /** | ||||||
|  |      * Used by main thread to alert other threads whether they should keep running or not | ||||||
|  |      */ | ||||||
|     private boolean shouldKeepRunning; |     private boolean shouldKeepRunning; | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Tracks all executors created | ||||||
|  |      */ | ||||||
|  |     private static List<ExecutorService> executors = new LinkedList<ExecutorService>(); | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Initializes the thread manager |      * Initializes the thread manager | ||||||
|      */ |      */ | ||||||
|     public void init(){ |     public void init(){ | ||||||
|         threadLock = new Semaphore(1); |         threadLock = new ReentrantLock(); | ||||||
|         activeThreads = new LinkedList<LabeledThread>(); |         activeThreads = new LinkedList<LabeledThread>(); | ||||||
|         loadingThreads = new LinkedList<LoadingThread>(); |         loadingThreads = new LinkedList<LoadingThread>(); | ||||||
|         shouldKeepRunning = true; |         shouldKeepRunning = true; | ||||||
| @ -48,7 +62,7 @@ public class ThreadManager { | |||||||
|      * Updates what threads are being tracked |      * Updates what threads are being tracked | ||||||
|      */ |      */ | ||||||
|     public void update(){ |     public void update(){ | ||||||
|         threadLock.acquireUninterruptibly(); |         threadLock.lock(); | ||||||
|         // |         // | ||||||
|         //remove loading threads |         //remove loading threads | ||||||
|         List<Thread> threadsToRemove = new LinkedList<Thread>(); |         List<Thread> threadsToRemove = new LinkedList<Thread>(); | ||||||
| @ -61,7 +75,7 @@ public class ThreadManager { | |||||||
|             loadingThreads.remove(thread); |             loadingThreads.remove(thread); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         threadLock.release(); |         threadLock.unlock(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -69,10 +83,10 @@ public class ThreadManager { | |||||||
|      * @param thread The thread to start |      * @param thread The thread to start | ||||||
|      */ |      */ | ||||||
|     public void start(ThreadLabel label, Thread thread){ |     public void start(ThreadLabel label, Thread thread){ | ||||||
|         threadLock.acquireUninterruptibly(); |         threadLock.lock(); | ||||||
|         activeThreads.add(new LabeledThread(label, thread)); |         activeThreads.add(new LabeledThread(label, thread)); | ||||||
|         thread.start(); |         thread.start(); | ||||||
|         threadLock.release(); |         threadLock.unlock(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -80,11 +94,11 @@ public class ThreadManager { | |||||||
|      * @param thread The loading thread to start |      * @param thread The loading thread to start | ||||||
|      */ |      */ | ||||||
|     public void start(LoadingThread thread){ |     public void start(LoadingThread thread){ | ||||||
|         threadLock.acquireUninterruptibly(); |         threadLock.lock(); | ||||||
|         activeThreads.add(new LabeledThread(ThreadLabel.LOADING, thread)); |         activeThreads.add(new LabeledThread(ThreadLabel.LOADING, thread)); | ||||||
|         loadingThreads.add(thread); |         loadingThreads.add(thread); | ||||||
|         thread.start(); |         thread.start(); | ||||||
|         threadLock.release(); |         threadLock.unlock(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -108,7 +122,7 @@ public class ThreadManager { | |||||||
|      */ |      */ | ||||||
|     public void close(){ |     public void close(){ | ||||||
|         this.shouldKeepRunning = false; |         this.shouldKeepRunning = false; | ||||||
|         threadLock.acquireUninterruptibly(); |         threadLock.lock(); | ||||||
| 
 | 
 | ||||||
|         //for some reason, server must be explicitly closed |         //for some reason, server must be explicitly closed | ||||||
|         if(Globals.server != null){ |         if(Globals.server != null){ | ||||||
| @ -125,9 +139,15 @@ public class ThreadManager { | |||||||
|         TerrainChunk.haltThreads(); |         TerrainChunk.haltThreads(); | ||||||
|         FoliageModel.haltThreads(); |         FoliageModel.haltThreads(); | ||||||
|         BlockChunkEntity.haltThreads(); |         BlockChunkEntity.haltThreads(); | ||||||
|         GriddedDataCellLoaderService.haltThreads(); |  | ||||||
|         PathfindingService.haltThreads(); |         PathfindingService.haltThreads(); | ||||||
| 
 | 
 | ||||||
|  |         /** | ||||||
|  |          * Halt all requested executors | ||||||
|  |          */ | ||||||
|  |         for(ExecutorService service : executors){ | ||||||
|  |             service.shutdownNow(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         // |         // | ||||||
|         //interrupt all threads |         //interrupt all threads | ||||||
|         for(int i = 0; i < 3; i++){ |         for(int i = 0; i < 3; i++){ | ||||||
| @ -150,7 +170,7 @@ public class ThreadManager { | |||||||
|                 CodeUtils.todo(e, "Handle failing to sleep while interrupting all other threads"); |                 CodeUtils.todo(e, "Handle failing to sleep while interrupting all other threads"); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         threadLock.release(); |         threadLock.unlock(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -166,7 +186,7 @@ public class ThreadManager { | |||||||
|      * @param label The label |      * @param label The label | ||||||
|      */ |      */ | ||||||
|     public void interruptLabel(ThreadLabel label){ |     public void interruptLabel(ThreadLabel label){ | ||||||
|         threadLock.acquireUninterruptibly(); |         threadLock.lock(); | ||||||
|         // |         // | ||||||
|         //interrupt threads |         //interrupt threads | ||||||
|         for(LabeledThread thread : activeThreads){ |         for(LabeledThread thread : activeThreads){ | ||||||
| @ -174,7 +194,24 @@ public class ThreadManager { | |||||||
|                 thread.getThread().interrupt(); |                 thread.getThread().interrupt(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         threadLock.release(); |         threadLock.unlock(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Requests a fixed-size thread pool | ||||||
|  |      * @param threads The number of threads | ||||||
|  |      * @return The executor | ||||||
|  |      */ | ||||||
|  |     public ExecutorService requestFixedThreadPool(int threads){ | ||||||
|  |         if(threads < 1){ | ||||||
|  |             throw new Error("Requested invalid number of threads! " + threads); | ||||||
|  |         } | ||||||
|  |         ExecutorService rVal = null; | ||||||
|  |         threadLock.lock(); | ||||||
|  |         rVal = Executors.newFixedThreadPool(threads); | ||||||
|  |         executors.add(rVal); | ||||||
|  |         threadLock.unlock(); | ||||||
|  |         return rVal; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,7 +4,6 @@ import java.util.HashMap; | |||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.concurrent.ExecutionException; | import java.util.concurrent.ExecutionException; | ||||||
| import java.util.concurrent.ExecutorService; | import java.util.concurrent.ExecutorService; | ||||||
| import java.util.concurrent.Executors; |  | ||||||
| import java.util.concurrent.Future; | import java.util.concurrent.Future; | ||||||
| import java.util.concurrent.locks.ReentrantLock; | import java.util.concurrent.locks.ReentrantLock; | ||||||
| 
 | 
 | ||||||
| @ -20,7 +19,7 @@ public class GriddedDataCellLoaderService { | |||||||
|     /** |     /** | ||||||
|      * Used for loading/unloading the cells |      * Used for loading/unloading the cells | ||||||
|      */ |      */ | ||||||
|     protected static final ExecutorService ioThreadService = Executors.newFixedThreadPool(ThreadCounts.GRIDDED_DATACELL_LOADING_THREADS); |     private ExecutorService ioThreadService = null; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Lock for structures in this service |      * Lock for structures in this service | ||||||
| @ -37,13 +36,20 @@ public class GriddedDataCellLoaderService { | |||||||
|      */ |      */ | ||||||
|     private static final Map<Long,Runnable> jobOperationMap = new HashMap<Long,Runnable>(); |     private static final Map<Long,Runnable> jobOperationMap = new HashMap<Long,Runnable>(); | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructor | ||||||
|  |      */ | ||||||
|  |     public GriddedDataCellLoaderService(){ | ||||||
|  |         this.ioThreadService = Globals.threadManager.requestFixedThreadPool(ThreadCounts.GRIDDED_DATACELL_LOADING_THREADS); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Queues an operation that requires a read or write of a location's file data. |      * Queues an operation that requires a read or write of a location's file data. | ||||||
|      * Guarantees that all operations will be run in order without losing any work. |      * Guarantees that all operations will be run in order without losing any work. | ||||||
|      * @param key The key for the cell |      * @param key The key for the cell | ||||||
|      * @param operation The operation to perform |      * @param operation The operation to perform | ||||||
|      */ |      */ | ||||||
|     protected static void queueLocationBasedOperation(long key, Runnable operation){ |     protected void queueLocationBasedOperation(long key, Runnable operation){ | ||||||
|         lock.lock(); |         lock.lock(); | ||||||
|         //if there is a job queued and we couldn't cancel it, wait |         //if there is a job queued and we couldn't cancel it, wait | ||||||
|         Future<?> job = queuedWorkLock.get(key); |         Future<?> job = queuedWorkLock.get(key); | ||||||
| @ -96,7 +102,7 @@ public class GriddedDataCellLoaderService { | |||||||
|     /** |     /** | ||||||
|      * Halts the threads for the data cell loader service |      * Halts the threads for the data cell loader service | ||||||
|      */ |      */ | ||||||
|     public static void haltThreads(){ |     public void haltThreads(){ | ||||||
|         ioThreadService.shutdownNow(); |         ioThreadService.shutdownNow(); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  | |||||||
| @ -9,7 +9,6 @@ import java.util.List; | |||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.concurrent.ExecutorService; | import java.util.concurrent.ExecutorService; | ||||||
| import java.util.concurrent.Executors; |  | ||||||
| import java.util.concurrent.Semaphore; | import java.util.concurrent.Semaphore; | ||||||
| import java.util.concurrent.locks.ReentrantLock; | import java.util.concurrent.locks.ReentrantLock; | ||||||
| 
 | 
 | ||||||
| @ -76,16 +75,21 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager | |||||||
|      */ |      */ | ||||||
|     static final double SIMULATION_DISTANCE_CUTOFF = 5; |     static final double SIMULATION_DISTANCE_CUTOFF = 5; | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * Used for generating physics chunks |  | ||||||
|      */ |  | ||||||
|     static final ExecutorService generationService = Executors.newFixedThreadPool(ThreadCounts.GRIDDED_DATACELL_PHYSICS_GEN_THREADS); |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Big number used when scanning for a data cell to spawn a macro object within |      * Big number used when scanning for a data cell to spawn a macro object within | ||||||
|      */ |      */ | ||||||
|     static final double MACRO_SCANNING_BIG_NUMBER = 10000; |     static final double MACRO_SCANNING_BIG_NUMBER = 10000; | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Used for generating physics chunks | ||||||
|  |      */ | ||||||
|  |     ExecutorService generationService = null; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The service for loading data cells from disk | ||||||
|  |      */ | ||||||
|  |     GriddedDataCellLoaderService loaderService; | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Tracks whether this manager has been flagged to unload cells or not |      * Tracks whether this manager has been flagged to unload cells or not | ||||||
|      */ |      */ | ||||||
| @ -192,7 +196,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager | |||||||
|             this.serverFluidManager == null || |             this.serverFluidManager == null || | ||||||
|             this.serverContentManager == null |             this.serverContentManager == null | ||||||
|         ){ |         ){ | ||||||
|             throw new IllegalStateException("Tried to create a GriddedDataCellManager with invalid parameters " + |             throw new Error("Tried to create a GriddedDataCellManager with invalid parameters " + | ||||||
|                 this.parent + " " + |                 this.parent + " " + | ||||||
|                 this.serverWorldData + " " + |                 this.serverWorldData + " " + | ||||||
|                 this.serverTerrainManager + " " + |                 this.serverTerrainManager + " " + | ||||||
| @ -201,6 +205,8 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager | |||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
|         this.pathfinder = new VoxelPathfinder(); |         this.pathfinder = new VoxelPathfinder(); | ||||||
|  |         this.loaderService = new GriddedDataCellLoaderService(); | ||||||
|  |         this.generationService = Globals.threadManager.requestFixedThreadPool(ThreadCounts.GRIDDED_DATACELL_PHYSICS_GEN_THREADS); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     /** |     /** | ||||||
| @ -549,7 +555,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager | |||||||
|                 //terrain is saved before tracking is removed. This makes sure that any side effects from calling savePositionToDisk (ie if it looks up the chunk that we're deleting) |                 //terrain is saved before tracking is removed. This makes sure that any side effects from calling savePositionToDisk (ie if it looks up the chunk that we're deleting) | ||||||
|                 //don't trigger the chunk to be re-created |                 //don't trigger the chunk to be re-created | ||||||
|                 Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Store data"); |                 Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Store data"); | ||||||
|                 GriddedDataCellLoaderService.queueLocationBasedOperation(key, () -> { |                 this.loaderService.queueLocationBasedOperation(key, () -> { | ||||||
|                     serverContentManager.saveSerializationToDisk(key, serializedEntities); |                     serverContentManager.saveSerializationToDisk(key, serializedEntities); | ||||||
|                     serverTerrainManager.savePositionToDisk(worldPos); |                     serverTerrainManager.savePositionToDisk(worldPos); | ||||||
|                 }); |                 }); | ||||||
| @ -768,7 +774,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager | |||||||
|      * Because cell hasn't been registered yet, no simulation is performed until the physics is created. |      * Because cell hasn't been registered yet, no simulation is performed until the physics is created. | ||||||
|      * @param worldPos |      * @param worldPos | ||||||
|      */ |      */ | ||||||
|     private static void runPhysicsGenerationThread( |     private void runPhysicsGenerationThread( | ||||||
|         Vector3i worldPos, |         Vector3i worldPos, | ||||||
|         Long key, |         Long key, | ||||||
|         PhysicsDataCell cell, |         PhysicsDataCell cell, | ||||||
| @ -805,7 +811,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager | |||||||
|             ServerEntityUtils.destroyEntity(blockEntity); |             ServerEntityUtils.destroyEntity(blockEntity); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         generationService.submit(() -> { |         this.generationService.submit(() -> { | ||||||
|             try { |             try { | ||||||
|                 BlockChunkData blockChunkData = realm.getServerWorldData().getServerBlockManager().getChunk(worldPos.x, worldPos.y, worldPos.z); |                 BlockChunkData blockChunkData = realm.getServerWorldData().getServerBlockManager().getChunk(worldPos.x, worldPos.y, worldPos.z); | ||||||
|                 ServerTerrainChunk terrainChunk = realm.getServerWorldData().getServerTerrainManager().getChunk(worldPos.x, worldPos.y, worldPos.z, ServerChunkCache.STRIDE_FULL_RES); |                 ServerTerrainChunk terrainChunk = realm.getServerWorldData().getServerTerrainManager().getChunk(worldPos.x, worldPos.y, worldPos.z, ServerChunkCache.STRIDE_FULL_RES); | ||||||
| @ -861,7 +867,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager | |||||||
| 
 | 
 | ||||||
|         Long key = this.getServerDataCellKey(localWorldPos); |         Long key = this.getServerDataCellKey(localWorldPos); | ||||||
|         //generate content |         //generate content | ||||||
|         GriddedDataCellLoaderService.queueLocationBasedOperation(key, () -> { |         this.loaderService.queueLocationBasedOperation(key, () -> { | ||||||
|             try { |             try { | ||||||
|                 serverContentManager.generateContentForDataCell(parent, localWorldPos, rVal, cellKey); |                 serverContentManager.generateContentForDataCell(parent, localWorldPos, rVal, cellKey); | ||||||
|             } catch(Error e){ |             } catch(Error e){ | ||||||
| @ -873,7 +879,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager | |||||||
|         //generates physics for the cell in a dedicated thread then finally registers |         //generates physics for the cell in a dedicated thread then finally registers | ||||||
|         loadedCellsLock.lock(); |         loadedCellsLock.lock(); | ||||||
|         PhysicsDataCell cell = posPhysicsMap.get(key); |         PhysicsDataCell cell = posPhysicsMap.get(key); | ||||||
|         GriddedDataCellManager.runPhysicsGenerationThread(localWorldPos,key,cell,this.posPhysicsMap,this.groundDataCells,this.cellTrackingMap,this.parent); |         this.runPhysicsGenerationThread(localWorldPos,key,cell,this.posPhysicsMap,this.groundDataCells,this.cellTrackingMap,this.parent); | ||||||
|         loadedCellsLock.unlock(); |         loadedCellsLock.unlock(); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -1047,8 +1053,8 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager | |||||||
|      * Stops the executor service |      * Stops the executor service | ||||||
|      */ |      */ | ||||||
|     public void halt(){ |     public void halt(){ | ||||||
|         generationService.shutdownNow(); |         this.generationService.shutdownNow(); | ||||||
|         GriddedDataCellLoaderService.ioThreadService.shutdownNow(); |         this.loaderService.haltThreads(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user