From 9ae823ef92ce713161c16f5ed8ff78389b667263 Mon Sep 17 00:00:00 2001 From: Jordan Ramsay Date: Tue, 3 Aug 2021 16:52:00 +1000 Subject: [PATCH] Patch to stop the java.util.ConcurrentModificationException. --- .../backend/instancing/InstanceManager.java | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java index 304bac4f0..636a59eb4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -3,7 +3,10 @@ package com.jozufozu.flywheel.backend.instancing; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.annotation.Nullable; @@ -19,8 +22,12 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL public final MaterialManager materialManager; - protected final ArrayList queuedAdditions; - protected final ConcurrentHashMap.KeySetView queuedUpdates; + //Thread locks to ensure concurrent access exceptions don't occur + private final ReadWriteLock queuedUpdatesLock = new ReentrantReadWriteLock(); + private final ReadWriteLock queuedAdditionsLock = new ReentrantReadWriteLock(); + + private final ArrayList queuedAdditions; + private final ConcurrentHashMap.KeySetView queuedUpdates; protected final Map instances; protected final Object2ObjectOpenHashMap tickableInstances; @@ -73,11 +80,20 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL }); } + + + + //suggested replacement ? + //Unable to confirm if the call to update(te) causes updates to the que. + //queuedUpdatesLock.writeLock().lock(); + //* queuedUpdates.forEach(te -> { queuedUpdates.remove(te); - update(te); - }); + });//*/ + //queuedUpdates.forEach(this::update); + //queuedUpdates.clear(); + //queuedUpdatesLock.writeLock().unlock(); } public void beginFrame(ActiveRenderInfo info) { @@ -118,7 +134,9 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL if (!Backend.getInstance() .canUseInstancing()) return; + queuedAdditionsLock.writeLock().lock(); queuedAdditions.add(obj); + queuedAdditionsLock.writeLock().unlock(); } public void update(T obj) { @@ -144,8 +162,9 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL public synchronized void queueUpdate(T obj) { if (!Backend.getInstance() .canUseInstancing()) return; - + queuedUpdatesLock.writeLock().lock(); queuedUpdates.add(obj); + queuedUpdatesLock.writeLock().unlock(); } public void onLightUpdate(T obj) { @@ -194,9 +213,12 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL } protected synchronized void processQueuedAdditions() { - if (queuedAdditions.size() > 0) { - queuedAdditions.forEach(this::addInternal); - queuedAdditions.clear(); + queuedAdditionsLock.writeLock().lock(); + ArrayList queued = new ArrayList<>(queuedAdditions); + queuedAdditions.clear(); + queuedAdditionsLock.writeLock().unlock(); + if (queued.size() > 0) { + queued.forEach(this::addInternal); } }