From 5282d1eb2f03413bb3df2e182e275be1ab094536 Mon Sep 17 00:00:00 2001 From: extio-de Date: Tue, 23 Dec 2025 14:38:51 +0100 Subject: [PATCH] feat(renderer): Add clear method to RendererWorkingSet for producer cleanup --- .../renderer/work/RendererWorkingSet.java | 2 + .../renderer/work/RendererWorkingSetImpl.java | 37 ++++++++++---- .../work/RendererWorkingSetImplTest.java | 48 +++++++++++++++++++ 3 files changed, 77 insertions(+), 10 deletions(-) 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 cfc904a..aa46492 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 @@ -18,6 +18,8 @@ public interface RendererWorkingSet { Map commit(Class producer, boolean clone); + void clear(Class producer); + void getLiveSet(List combinedLiveSet); } 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 bf2c5e0..2e239c6 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 @@ -74,21 +74,21 @@ public class RendererWorkingSetImpl implements RendererWorkingSet { final var previousWorkMap = previousWork.get(); if (previousWorkMap != null) { - final var releasedBoClasses = this.obtainSetFromPool(); - for (final RenderingBo renderingBO : previousWorkMap.values()) { - if (releasedBoClasses.add(renderingBO.getClass())) { - renderingBO.closeStatic(); - } - this.rendererBoPool.release(renderingBO); - } - - this.returnMapToPool(previousWorkMap); - this.returnSetToPool(releasedBoClasses); + this.releaseBoClasses(previousWorkMap); } return rendererWork.next(); } + @Override + public void clear(final Class producer) { + final RendererWork rendererWork = this.workingSet.remove(producer); + if (rendererWork != null) { + this.releaseBoClasses(rendererWork.live()); + this.releaseBoClasses(rendererWork.next()); + } + } + @Override public void getLiveSet(final List combinedLiveSet) { this.workingSet.values().forEach(rendererWork -> combinedLiveSet.addAll(rendererWork.live().values())); @@ -98,6 +98,23 @@ public class RendererWorkingSetImpl implements RendererWorkingSet { return this.workingSet.computeIfAbsent(producer, 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) { 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 f135426..870c97b 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 @@ -146,6 +146,54 @@ public class RendererWorkingSetImplTest { assertTrue(live.isEmpty()); } + @Test + void clearRemovesProducerAndReleasesWork() { + final var bo1 = new TestBoA(); + bo1.setId("bo1"); + final var bo2 = new TestBoB(); + bo2.setId("bo2"); + + this.workingSet.add(TestModuleA.class, bo1); + this.workingSet.commit(TestModuleA.class, false); + this.workingSet.add(TestModuleA.class, bo2); + + // Before clear + final List liveBefore = new ArrayList<>(); + this.workingSet.getLiveSet(liveBefore); + assertTrue(liveBefore.contains(bo1)); + assertNotNull(this.workingSet.get(TestModuleA.class, "bo2")); + + this.workingSet.clear(TestModuleA.class); + + // After clear + final List liveAfter = new ArrayList<>(); + this.workingSet.getLiveSet(liveAfter); + assertTrue(liveAfter.isEmpty()); + + final var uncommittedAfter = this.workingSet.getUncommittedWork(TestModuleA.class); + assertTrue(uncommittedAfter.isEmpty()); + + verify(this.renderingBoPool, times(1)).release(bo1); + verify(this.renderingBoPool, times(1)).release(bo2); + assertEquals(1, bo1.closeStaticCalls()); + assertEquals(1, bo2.closeStaticCalls()); + } + + @Test + void clearOnUnknownProducerDoesNothing() { + final RenderingBo bo1 = mock(RenderingBo.class); + when(bo1.getId()).thenReturn("bo1"); + this.workingSet.add(TestModuleA.class, bo1); + this.workingSet.commit(TestModuleA.class, false); + + this.workingSet.clear(TestModuleC.class); + + final List live = new ArrayList<>(); + this.workingSet.getLiveSet(live); + assertEquals(1, live.size()); + assertTrue(live.contains(bo1)); + } + @Test void secondCommitReleasesPreviousLiveWorkAndCallsCloseStaticOncePerClass() { final var bo1 = new TestBoA();