diff options
author | Martin Robertz <dream-master@gmx.net> | 2021-01-19 08:36:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-19 08:36:20 +0100 |
commit | 298ee98708c3e027631076dbc0eb83aa36a72580 (patch) | |
tree | b308cebaa8bb67015ee49286fd256c35f567b582 /src/main/java/gregtech/api/threads | |
parent | ab5523d1e38f9fbbcf11a6b896f723f950b195a2 (diff) | |
parent | 17225fb5d3727f677121ec6017d5f09b632af9a9 (diff) | |
download | GT5-Unofficial-298ee98708c3e027631076dbc0eb83aa36a72580.tar.gz GT5-Unofficial-298ee98708c3e027631076dbc0eb83aa36a72580.tar.bz2 GT5-Unofficial-298ee98708c3e027631076dbc0eb83aa36a72580.zip |
Merge pull request #414 from GTNewHorizons/maybe_fix_cme_in_machine_update_thread
Do some locking around getTileEntity to avoid CMEs on the main thread
Diffstat (limited to 'src/main/java/gregtech/api/threads')
-rw-r--r-- | src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java b/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java index 8f7a84e2cb..6564cf316a 100644 --- a/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java +++ b/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java @@ -1,5 +1,8 @@ package gregtech.api.threads; + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; import gregtech.GT_Mod; import gregtech.api.GregTech_API; import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable; @@ -15,6 +18,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; public class GT_Runnable_MachineBlockUpdate implements Runnable { // used by runner thread @@ -23,6 +27,9 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable { private final Set<ChunkCoordinates> visited = new HashSet<>(80); private final Queue<ChunkCoordinates> tQueue = new LinkedList<>(); + // Locking + private static ReentrantLock lock = new ReentrantLock(); + // Threading private static final ThreadFactory THREAD_FACTORY = r -> { Thread thread = new Thread(r); @@ -40,6 +47,16 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable { } + @SubscribeEvent + public void onServerTick(TickEvent.ServerTickEvent aEvent) { + // Using onServerTick because there's race conditions in updateTrackedEntities() which is called AFTER the END phase of onWorldTick + if (aEvent.phase == TickEvent.Phase.START) { + lock.lock(); + } else { + lock.unlock(); + } + } + public static boolean isEnabled() { return isEnabled; } @@ -101,8 +118,19 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable { try { while (!tQueue.isEmpty()) { final ChunkCoordinates aCoords = tQueue.poll(); - TileEntity tTileEntity = world.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ); - + final TileEntity tTileEntity; + final boolean isMachineBlock; + + // This might load a chunk... which might load a TileEntity... which might get added to `loadedTileEntityList`... which might be in the process + // of being iterated over during `UpdateEntities()`... which might cause a ConcurrentModificationException. So, lock that shit. + lock.lock(); + try { + tTileEntity = world.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ); + isMachineBlock = GregTech_API.isMachineBlock(world.getBlock(aCoords.posX, aCoords.posY, aCoords.posZ), world.getBlockMetadata(aCoords.posX, aCoords.posY, aCoords.posZ)); + } finally { + lock.unlock(); + } + // See if the block itself needs an update if (tTileEntity instanceof IMachineBlockUpdateable) ((IMachineBlockUpdateable) tTileEntity).onMachineBlockUpdate(); @@ -113,7 +141,7 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable { // 3) If the block at the coordinates is marked as a machine block if (visited.size() < 5 || (tTileEntity instanceof IMachineBlockUpdateable && ((IMachineBlockUpdateable) tTileEntity).isMachineBlockUpdateRecursive()) - || GregTech_API.isMachineBlock(world.getBlock(aCoords.posX, aCoords.posY, aCoords.posZ), world.getBlockMetadata(aCoords.posX, aCoords.posY, aCoords.posZ))) + || isMachineBlock) { ChunkCoordinates tCoords; |