From 3e17849093faf7b881316d6b2de68b28cf1047f2 Mon Sep 17 00:00:00 2001 From: extio-de Date: Thu, 25 Dec 2025 13:23:25 +0100 Subject: [PATCH] feat(renderer): Implement getOrAcquire and remove methods in RendererWorkingSet interface and update RendererWorkingSetImpl --- .../game_engine/renderer/g2d/G2DRenderer.java | 10 ++- .../renderer/work/RendererWorkingSet.java | 2 + .../renderer/work/RendererWorkingSetImpl.java | 67 ++++++++----------- .../work/RendererWorkingSetImplTest.java | 25 ++----- 4 files changed, 42 insertions(+), 62 deletions(-) diff --git a/src/main/java/de/extio/game_engine/renderer/g2d/G2DRenderer.java b/src/main/java/de/extio/game_engine/renderer/g2d/G2DRenderer.java index 7724bf8..66f8720 100644 --- a/src/main/java/de/extio/game_engine/renderer/g2d/G2DRenderer.java +++ b/src/main/java/de/extio/game_engine/renderer/g2d/G2DRenderer.java @@ -2,7 +2,6 @@ package de.extio.game_engine.renderer.g2d; import java.awt.Color; import java.awt.EventQueue; -import java.awt.Font; import java.awt.Graphics2D; import java.awt.Toolkit; import java.awt.image.BufferedImage; @@ -25,7 +24,6 @@ import org.slf4j.LoggerFactory; import de.extio.game_engine.module.AbstractClientModule; import de.extio.game_engine.renderer.Renderer; import de.extio.game_engine.renderer.RendererData; -import de.extio.game_engine.renderer.g2d.G2DRenderer.G2DRendererModule; import de.extio.game_engine.renderer.g2d.bo.rendering.G2DAbstractRenderingBo; import de.extio.game_engine.renderer.g2d.bo.rendering.G2DDrawBackground; import de.extio.game_engine.renderer.g2d.bo.rendering.G2DDrawFont; @@ -54,6 +52,8 @@ public class G2DRenderer implements Renderer { private final List renderingBOs = new ArrayList<>(); + private final Map, RenderingBo> usedRenderingBoTypes = new HashMap<>(); + private volatile G2DMainFrame mainFrame; private String rendererModuleId; @@ -190,8 +190,10 @@ public class G2DRenderer implements Renderer { screenGraphics.setColor(Color.BLACK); screenGraphics.fillRect(0, 0, viewPortDimension.getX(), viewPortDimension.getY()); + usedRenderingBoTypes.clear(); for (final RenderingBo renderingBO : this.renderingBOs) { if (renderingBO instanceof final G2DAbstractRenderingBo g2dAbstractRenderingBo) { + usedRenderingBoTypes.putIfAbsent(g2dAbstractRenderingBo.getClass(), g2dAbstractRenderingBo); g2dAbstractRenderingBo.render(screenGraphics, this.rendererData.getRendererControl().getScaleFactor(), false); if (takeScreenshot_ && g2dAbstractRenderingBo.isScreenshotRelevant()) { g2dAbstractRenderingBo.render(screenshotGraphics, this.rendererData.getRendererControl().getScaleFactor(), true); @@ -199,7 +201,9 @@ public class G2DRenderer implements Renderer { } } - this.rendererData.getRendererWorkingSet().get(this.rendererModuleId, "G2DRenderer_tooltip").closeStatic(); + for (final RenderingBo bo : usedRenderingBoTypes.values()) { + bo.closeStatic(); + } // // Rendering cycle END diff --git a/src/main/java/de/extio/game_engine/renderer/work/RendererWorkingSet.java b/src/main/java/de/extio/game_engine/renderer/work/RendererWorkingSet.java index ebc89f2..cc58682 100644 --- a/src/main/java/de/extio/game_engine/renderer/work/RendererWorkingSet.java +++ b/src/main/java/de/extio/game_engine/renderer/work/RendererWorkingSet.java @@ -17,6 +17,8 @@ public interface RendererWorkingSet { T get(String producerId, String id, Class type); T getOrAcquire(String producerId, String id, Class type); + + void remove(String producerId, String id); Map getUncommittedWork(String producerId); diff --git a/src/main/java/de/extio/game_engine/renderer/work/RendererWorkingSetImpl.java b/src/main/java/de/extio/game_engine/renderer/work/RendererWorkingSetImpl.java index 713553e..84c4d10 100644 --- a/src/main/java/de/extio/game_engine/renderer/work/RendererWorkingSetImpl.java +++ b/src/main/java/de/extio/game_engine/renderer/work/RendererWorkingSetImpl.java @@ -31,22 +31,38 @@ public class RendererWorkingSetImpl implements RendererWorkingSet { @Override public void put(final String producerId, final RenderingBo work) { - this.getWorkingSetByProducer(producerId) + final var previous = this.getWorkingSetByProducer(producerId) .next() .put(work.getId(), work); + if (previous != null) { + this.rendererBoPool.release(previous); + } } @Override public void put(final String producerId, final List work) { final var nextMap = this.getWorkingSetByProducer(producerId).next(); for (final RenderingBo bo : work) { - nextMap.put(bo.getId(), bo); + final var previous = nextMap.put(bo.getId(), bo); + if (previous != null) { + this.rendererBoPool.release(previous); + } + } + } + + @Override + public void remove(final String producerId, final String id) { + final var previous = this.getWorkingSetByProducer(producerId) + .next() + .remove(id); + if (previous != null) { + this.rendererBoPool.release(previous); } } @Override public Map getUncommittedWork(final String producerId) { - return this.getWorkingSetByProducer(producerId).next(); + return Map.copyOf(this.getWorkingSetByProducer(producerId).next()); } @Override @@ -74,25 +90,26 @@ public class RendererWorkingSetImpl implements RendererWorkingSet { @Override public Map commit(final String producerId, final boolean clone) { - final AtomicReference> previousWork = new AtomicReference<>(); + final AtomicReference> previousLiveRef = new AtomicReference<>(); final RendererWork rendererWork = this.workingSet.compute(producerId, (k, v) -> { if (v == null) { return new RendererWork(this.obtainMapFromPool(), this.obtainMapFromPool()); } - previousWork.set(v.live()); + previousLiveRef.set(v.live()); if (clone) { final Map newNext = this.obtainMapFromPool(); newNext.putAll(v.next()); return new RendererWork(v.next(), newNext); } else { + v.live().values().forEach(this.rendererBoPool::release); return new RendererWork(v.next(), this.obtainMapFromPool()); } }); - final var previousWorkMap = previousWork.get(); - if (previousWorkMap != null) { - this.releaseBoClasses(previousWorkMap); + final var previousLiveSet = previousLiveRef.get(); + if (previousLiveSet != null) { + this.returnMapToPool(previousLiveSet); } return rendererWork.next(); @@ -102,8 +119,8 @@ public class RendererWorkingSetImpl implements RendererWorkingSet { public void clear(final String producerId) { final RendererWork rendererWork = this.workingSet.remove(producerId); if (rendererWork != null) { - this.releaseBoClasses(rendererWork.live()); - this.releaseBoClasses(rendererWork.next()); + rendererWork.live().values().forEach(this.rendererBoPool::release); + rendererWork.next().values().forEach(this.rendererBoPool::release); } } @@ -120,23 +137,6 @@ public class RendererWorkingSetImpl implements RendererWorkingSet { return this.workingSet.computeIfAbsent(producerId, k -> new RendererWork(this.obtainMapFromPool(), this.obtainMapFromPool())); } - private void releaseBoClasses(final Map work) { - if (work == null || work.isEmpty()) { - return; - } - - final var releasedBoClasses = this.obtainSetFromPool(); - for (final RenderingBo renderingBO : work.values()) { - if (releasedBoClasses.add(renderingBO.getClass())) { - renderingBO.closeStatic(); - } - this.rendererBoPool.release(renderingBO); - } - - this.returnMapToPool(work); - this.returnSetToPool(releasedBoClasses); - } - private Map obtainMapFromPool() { var map = this.mapsPool.poll(); if (map == null) { @@ -150,19 +150,6 @@ public class RendererWorkingSetImpl implements RendererWorkingSet { this.mapsPool.offer(map); } - private Set> obtainSetFromPool() { - var set = this.setsPool.poll(); - if (set == null) { - set = new HashSet<>(); - } - return set; - } - - private void returnSetToPool(final Set> set) { - set.clear(); - this.setsPool.offer(set); - } - private static record RendererWork(Map live, Map next) { } diff --git a/src/test/java/de/extio/game_engine/renderer/work/RendererWorkingSetImplTest.java b/src/test/java/de/extio/game_engine/renderer/work/RendererWorkingSetImplTest.java index dd0c745..fef79b3 100644 --- a/src/test/java/de/extio/game_engine/renderer/work/RendererWorkingSetImplTest.java +++ b/src/test/java/de/extio/game_engine/renderer/work/RendererWorkingSetImplTest.java @@ -10,7 +10,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -85,8 +84,9 @@ public class RendererWorkingSetImplTest { final var returnedUncommitted = this.workingSet.commit(this.moduleA.getId(), false); final var currentUncommitted = this.workingSet.getUncommittedWork(this.moduleA.getId()); - assertSame(currentUncommitted, returnedUncommitted); + assertTrue(returnedUncommitted.isEmpty()); assertTrue(currentUncommitted.isEmpty()); + assertEquals(returnedUncommitted, currentUncommitted); final List live = new ArrayList<>(); this.workingSet.getLiveSet(live, null); @@ -109,7 +109,7 @@ public class RendererWorkingSetImplTest { final var returnedUncommitted = this.workingSet.commit(this.moduleA.getId(), true); final var currentUncommitted = this.workingSet.getUncommittedWork(this.moduleA.getId()); - assertSame(currentUncommitted, returnedUncommitted); + assertEquals(currentUncommitted, returnedUncommitted); assertEquals(Map.of("bo1", bo1, "bo2", bo2), currentUncommitted); final List live = new ArrayList<>(); @@ -186,8 +186,6 @@ public class RendererWorkingSetImplTest { verify(this.renderingBoPool, times(1)).release(bo1); verify(this.renderingBoPool, times(1)).release(bo2); - assertEquals(1, bo1.closeStaticCalls()); - assertEquals(1, bo2.closeStaticCalls()); } @Test @@ -206,7 +204,7 @@ public class RendererWorkingSetImplTest { } @Test - void secondCommitReleasesPreviousLiveWorkAndCallsCloseStaticOncePerClass() { + void secondCommitReleasesPreviousLiveWork() { final var bo1 = new TestBoA(); bo1.setId("bo1"); final var bo2 = new TestBoA(); @@ -223,11 +221,6 @@ public class RendererWorkingSetImplTest { verify(this.renderingBoPool, times(1)).release(bo1); verify(this.renderingBoPool, times(1)).release(bo2); - - // closeStatic() is called exactly once per class, so one of bo1 or bo2 has it called - final int totalCloseStaticCallsForTestBoA = bo1.closeStaticCalls() + bo2.closeStaticCalls(); - assertEquals(1, totalCloseStaticCallsForTestBoA); - assertEquals(0, bo3.closeStaticCalls()); } @Test @@ -362,8 +355,6 @@ public class RendererWorkingSetImplTest { private static abstract class TestBoBase implements RenderingBo { - private final AtomicInteger closeStaticCalls = new AtomicInteger(); - private String id; @Override @@ -483,13 +474,9 @@ public class RendererWorkingSetImplTest { @Override public void closeStatic() { - this.closeStaticCalls.incrementAndGet(); + } - - public int closeStaticCalls() { - return this.closeStaticCalls.get(); - } - + @Override public void setRendererData(final RendererData RendererData) { }