diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java index e2976e4a8..05a90f292 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java @@ -1,8 +1,8 @@ package com.jozufozu.flywheel.impl.instancing.manager; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Consumer; import org.joml.FrustumIntersection; @@ -16,10 +16,10 @@ import com.jozufozu.flywheel.impl.instancing.ratelimit.BandedPrimeLimiter; import com.jozufozu.flywheel.impl.instancing.ratelimit.DistanceUpdateLimiter; import com.jozufozu.flywheel.impl.instancing.ratelimit.NonLimiter; import com.jozufozu.flywheel.impl.instancing.storage.Storage; +import com.jozufozu.flywheel.impl.instancing.storage.Transaction; public abstract class InstanceManager { - private final Set queuedAdditions = new HashSet<>(64); - private final Set queuedUpdates = new HashSet<>(64); + private final Queue> queue = new ConcurrentLinkedQueue<>(); protected DistanceUpdateLimiter tickLimiter; protected DistanceUpdateLimiter frameLimiter; @@ -61,9 +61,7 @@ public abstract class InstanceManager { return; } - synchronized (queuedAdditions) { - queuedAdditions.add(obj); - } + queue.add(Transaction.add(obj)); } /** @@ -90,9 +88,7 @@ public abstract class InstanceManager { return; } - synchronized (queuedUpdates) { - queuedUpdates.add(obj); - } + queue.add(Transaction.update(obj)); } public void remove(T obj) { @@ -107,37 +103,11 @@ public abstract class InstanceManager { getStorage().invalidate(); } - protected void processQueuedAdditions() { - if (queuedAdditions.isEmpty()) { - return; - } - - List queued; - - synchronized (queuedAdditions) { - queued = List.copyOf(queuedAdditions); - queuedAdditions.clear(); - } - - if (!queued.isEmpty()) { - queued.forEach(getStorage()::add); - } - } - - protected void processQueuedUpdates() { - if (queuedUpdates.isEmpty()) { - return; - } - - List queued; - - synchronized (queuedUpdates) { - queued = List.copyOf(queuedUpdates); - queuedUpdates.clear(); - } - - if (!queued.isEmpty()) { - queued.forEach(getStorage()::update); + protected void processQueue() { + var storage = getStorage(); + Transaction transaction; + while ((transaction = queue.poll()) != null) { + transaction.apply(storage); } } @@ -152,8 +122,7 @@ public abstract class InstanceManager { */ public void tick(TaskExecutor executor, double cameraX, double cameraY, double cameraZ) { tickLimiter.tick(); - processQueuedAdditions(); - processQueuedUpdates(); + processQueue(); var instances = getStorage().getTickableInstances(); distributeWork(executor, instances, instance -> tickInstance(instance, cameraX, cameraY, cameraZ)); @@ -167,8 +136,7 @@ public abstract class InstanceManager { public void beginFrame(TaskExecutor executor, double cameraX, double cameraY, double cameraZ, FrustumIntersection frustum) { frameLimiter.tick(); - processQueuedAdditions(); - processQueuedUpdates(); + processQueue(); var instances = getStorage().getDynamicInstances(); distributeWork(executor, instances, instance -> updateInstance(instance, cameraX, cameraY, cameraZ, frustum)); diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/storage/Action.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/storage/Action.java new file mode 100644 index 000000000..99f993f90 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/storage/Action.java @@ -0,0 +1,7 @@ +package com.jozufozu.flywheel.impl.instancing.storage; + +public enum Action { + ADD, + REMOVE, + UPDATE, +} diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/storage/Transaction.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/storage/Transaction.java new file mode 100644 index 000000000..fb127515c --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/storage/Transaction.java @@ -0,0 +1,23 @@ +package com.jozufozu.flywheel.impl.instancing.storage; + +public record Transaction(T obj, Action action) { + public static Transaction add(T obj) { + return new Transaction<>(obj, Action.ADD); + } + + public static Transaction remove(T obj) { + return new Transaction<>(obj, Action.REMOVE); + } + + public static Transaction update(T obj) { + return new Transaction<>(obj, Action.UPDATE); + } + + public void apply(Storage storage) { + switch (action) { + case ADD -> storage.add(obj); + case REMOVE -> storage.remove(obj); + case UPDATE -> storage.update(obj); + } + } +}