Patch to stop the java.util.ConcurrentModificationException.

This commit is contained in:
Jordan Ramsay 2021-08-03 16:52:00 +10:00
parent 94c5b4455d
commit bf27108b18

View file

@ -3,7 +3,10 @@ package com.jozufozu.flywheel.backend.instancing;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -19,8 +22,12 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
public final MaterialManager<?> materialManager; public final MaterialManager<?> materialManager;
protected final ArrayList<T> queuedAdditions; //Thread locks to ensure concurrent access exceptions don't occur
protected final ConcurrentHashMap.KeySetView<T, Boolean> queuedUpdates; private final ReadWriteLock queuedUpdatesLock = new ReentrantReadWriteLock();
private final ReadWriteLock queuedAdditionsLock = new ReentrantReadWriteLock();
private final ArrayList<T> queuedAdditions;
private final ConcurrentHashMap.KeySetView<T, Boolean> queuedUpdates;
protected final Map<T, IInstance> instances; protected final Map<T, IInstance> instances;
protected final Object2ObjectOpenHashMap<T, ITickableInstance> tickableInstances; protected final Object2ObjectOpenHashMap<T, ITickableInstance> tickableInstances;
@ -73,11 +80,20 @@ public abstract class InstanceManager<T> 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.forEach(te -> {
queuedUpdates.remove(te); queuedUpdates.remove(te);
update(te); update(te);
}); });//*/
//queuedUpdates.forEach(this::update);
//queuedUpdates.clear();
//queuedUpdatesLock.writeLock().unlock();
} }
public void beginFrame(ActiveRenderInfo info) { public void beginFrame(ActiveRenderInfo info) {
@ -118,7 +134,9 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
if (!Backend.getInstance() if (!Backend.getInstance()
.canUseInstancing()) return; .canUseInstancing()) return;
queuedAdditionsLock.writeLock().lock();
queuedAdditions.add(obj); queuedAdditions.add(obj);
queuedAdditionsLock.writeLock().unlock();
} }
public void update(T obj) { public void update(T obj) {
@ -144,8 +162,9 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
public synchronized void queueUpdate(T obj) { public synchronized void queueUpdate(T obj) {
if (!Backend.getInstance() if (!Backend.getInstance()
.canUseInstancing()) return; .canUseInstancing()) return;
queuedUpdatesLock.writeLock().lock();
queuedUpdates.add(obj); queuedUpdates.add(obj);
queuedUpdatesLock.writeLock().unlock();
} }
public void onLightUpdate(T obj) { public void onLightUpdate(T obj) {
@ -194,9 +213,12 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
} }
protected synchronized void processQueuedAdditions() { protected synchronized void processQueuedAdditions() {
if (queuedAdditions.size() > 0) { queuedAdditionsLock.writeLock().lock();
queuedAdditions.forEach(this::addInternal); ArrayList<T> queued = new ArrayList<>(queuedAdditions);
queuedAdditions.clear(); queuedAdditions.clear();
queuedAdditionsLock.writeLock().unlock();
if (queued.size() > 0) {
queued.forEach(this::addInternal);
} }
} }