Files
OpenMaidEngine/engine/Age.Engine.Tests/GfxStateConcurrencyTests.cs
gamer147 8ac9e6675b fix(gfx): serialize GetOrCreate/Register/Release on _lock (compositor race)
Once sleep paces the VM thread, the main-thread compositor's SnapshotVisibleObjects
truly overlaps VM-thread _objects/_registry writes. GetOrCreate/Register/Release were
unlocked -> 'Destination array is not long enough' under concurrent enumeration.
_lock is re-entrant so BindDraw/EraseRange (already locked) stay correct. 52 green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 09:01:13 -04:00

29 lines
875 B
C#

using System.Threading.Tasks;
using Age.Engine.Model;
using Xunit;
public class GfxStateConcurrencyTests
{
[Fact]
public void Snapshot_DoesNotThrow_WhileObjectsMutate()
{
var gfx = new GfxState();
var stop = false;
var writer = Task.Run(() =>
{
long h = 0;
while (!stop)
{
h = (h + 1) % 64;
gfx.BindDraw(h, 0, 0, 0, 10, 10, 0, 0); // GetOrCreate + visible
gfx.GetOrCreate(h + 100); // bare create
if (h % 8 == 0) gfx.Release(h + 100); // remove
}
});
// Hammer the reader concurrently; a dictionary mutated during enumeration would throw here.
for (int i = 0; i < 20000; i++) { var _ = gfx.SnapshotVisibleObjects(); }
stop = true;
writer.Wait();
}
}