Merge pull request #22 from 34638a/dev

Patch to stop the java.util.ConcurrentModificationException.
This commit is contained in:
Jozufozu 2021-08-04 14:16:47 -07:00 committed by GitHub
commit f21566d1fc

View file

@ -1,9 +1,16 @@
package com.jozufozu.flywheel.backend.instancing; package com.jozufozu.flywheel.backend.instancing;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Consumer;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -11,6 +18,7 @@ import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.material.MaterialManager; import com.jozufozu.flywheel.backend.material.MaterialManager;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3f; import net.minecraft.util.math.vector.Vector3f;
@ -19,8 +27,8 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
public final MaterialManager<?> materialManager; public final MaterialManager<?> materialManager;
protected final ArrayList<T> queuedAdditions; private final Set<T> queuedAdditions;
protected final ConcurrentHashMap.KeySetView<T, Boolean> queuedUpdates; private final Set<T> 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;
@ -31,8 +39,8 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
public InstanceManager(MaterialManager<?> materialManager) { public InstanceManager(MaterialManager<?> materialManager) {
this.materialManager = materialManager; this.materialManager = materialManager;
this.queuedUpdates = ConcurrentHashMap.newKeySet(64); this.queuedUpdates = new HashSet<>(64);
this.queuedAdditions = new ArrayList<>(64); this.queuedAdditions = new HashSet<>(64);
this.instances = new HashMap<>(); this.instances = new HashMap<>();
this.dynamicInstances = new Object2ObjectOpenHashMap<>(); this.dynamicInstances = new Object2ObjectOpenHashMap<>();
@ -49,6 +57,7 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
public void tick(double cameraX, double cameraY, double cameraZ) { public void tick(double cameraX, double cameraY, double cameraZ) {
tick++; tick++;
processQueuedUpdates();
// integer camera pos // integer camera pos
int cX = (int) cameraX; int cX = (int) cameraX;
@ -72,12 +81,6 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) instance.tick(); if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) instance.tick();
}); });
} }
queuedUpdates.forEach(te -> {
queuedUpdates.remove(te);
update(te);
});
} }
public void beginFrame(ActiveRenderInfo info) { public void beginFrame(ActiveRenderInfo info) {
@ -118,7 +121,9 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
if (!Backend.getInstance() if (!Backend.getInstance()
.canUseInstancing()) return; .canUseInstancing()) return;
queuedAdditions.add(obj); synchronized (queuedAdditions) {
queuedAdditions.add(obj);
}
} }
public void update(T obj) { public void update(T obj) {
@ -144,8 +149,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;
synchronized (queuedUpdates) {
queuedUpdates.add(obj); queuedUpdates.add(obj);
}
} }
public void onLightUpdate(T obj) { public void onLightUpdate(T obj) {
@ -176,7 +182,6 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
tickableInstances.clear(); tickableInstances.clear();
} }
@SuppressWarnings("unchecked")
@Nullable @Nullable
protected <I extends T> IInstance getInstance(I obj, boolean create) { protected <I extends T> IInstance getInstance(I obj, boolean create) {
if (!Backend.getInstance() if (!Backend.getInstance()
@ -193,11 +198,30 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
} }
} }
protected synchronized void processQueuedAdditions() { protected void processQueuedAdditions() {
if (queuedAdditions.size() > 0) { ArrayList<T> queued;
queuedAdditions.forEach(this::addInternal);
synchronized (queuedAdditions) {
queued = new ArrayList<>(queuedAdditions);
queuedAdditions.clear(); queuedAdditions.clear();
} }
if (queued.size() > 0) {
queued.forEach(this::addInternal);
}
}
protected void processQueuedUpdates() {
ArrayList<T> queued;
synchronized (queuedUpdates) {
queued = new ArrayList<>(queuedUpdates);
queuedUpdates.clear();
}
if (queued.size() > 0) {
queued.forEach(this::update);
}
} }
protected boolean shouldFrameUpdate(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { protected boolean shouldFrameUpdate(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) {