mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-29 08:26:37 +01:00
Simplify synchronization
- Use `synchronized` on the queue sets in favor of explicit locks. - Updates and additions work the same now - Move updates processing to separate function
This commit is contained in:
parent
9ae823ef92
commit
7eb0284db9
1 changed files with 37 additions and 35 deletions
|
@ -1,12 +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.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.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@ -14,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;
|
||||||
|
@ -22,12 +27,8 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
||||||
|
|
||||||
public final MaterialManager<?> materialManager;
|
public final MaterialManager<?> materialManager;
|
||||||
|
|
||||||
//Thread locks to ensure concurrent access exceptions don't occur
|
private final Set<T> queuedAdditions;
|
||||||
private final ReadWriteLock queuedUpdatesLock = new ReentrantReadWriteLock();
|
private final Set<T> queuedUpdates;
|
||||||
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;
|
||||||
|
@ -38,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<>();
|
||||||
|
@ -56,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;
|
||||||
|
@ -79,21 +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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//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) {
|
public void beginFrame(ActiveRenderInfo info) {
|
||||||
|
@ -134,9 +121,9 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
||||||
if (!Backend.getInstance()
|
if (!Backend.getInstance()
|
||||||
.canUseInstancing()) return;
|
.canUseInstancing()) return;
|
||||||
|
|
||||||
queuedAdditionsLock.writeLock().lock();
|
synchronized (queuedAdditions) {
|
||||||
queuedAdditions.add(obj);
|
queuedAdditions.add(obj);
|
||||||
queuedAdditionsLock.writeLock().unlock();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(T obj) {
|
public void update(T obj) {
|
||||||
|
@ -162,9 +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;
|
||||||
queuedUpdatesLock.writeLock().lock();
|
synchronized (queuedUpdates) {
|
||||||
queuedUpdates.add(obj);
|
queuedUpdates.add(obj);
|
||||||
queuedUpdatesLock.writeLock().unlock();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onLightUpdate(T obj) {
|
public void onLightUpdate(T obj) {
|
||||||
|
@ -195,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()
|
||||||
|
@ -212,16 +198,32 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void processQueuedAdditions() {
|
protected void processQueuedAdditions() {
|
||||||
queuedAdditionsLock.writeLock().lock();
|
ArrayList<T> queued;
|
||||||
ArrayList<T> queued = new ArrayList<>(queuedAdditions);
|
|
||||||
|
synchronized (queuedAdditions) {
|
||||||
|
queued = new ArrayList<>(queuedAdditions);
|
||||||
queuedAdditions.clear();
|
queuedAdditions.clear();
|
||||||
queuedAdditionsLock.writeLock().unlock();
|
}
|
||||||
|
|
||||||
if (queued.size() > 0) {
|
if (queued.size() > 0) {
|
||||||
queued.forEach(this::addInternal);
|
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) {
|
||||||
int dX = worldPos.getX() - cX;
|
int dX = worldPos.getX() - cX;
|
||||||
int dY = worldPos.getY() - cY;
|
int dY = worldPos.getY() - cY;
|
||||||
|
|
Loading…
Reference in a new issue