refactor(app): own native window callback lifetime
Publish the fixed Silk callback binding before acquisition, quiesce admitted callbacks before teardown, and retain failed physical detach ownership for retry. Preserve the frozen callback order while covering partial event accessors, concurrency, reentrancy, and shutdown completion. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
476c2e6de1
commit
18d4b999de
7 changed files with 1416 additions and 50 deletions
|
|
@ -22,31 +22,25 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
"Samples = startupQuality.MsaaSamples",
|
||||
"Window.Create(options)",
|
||||
"_displayFramePacing.BindSurface(",
|
||||
"_window.Load += OnLoad;",
|
||||
"_window.Update += OnUpdate;",
|
||||
"_window.Render += OnRender;",
|
||||
"_window.Render += _displayFramePacing.OnFrameRendered;",
|
||||
"_window.Closing += OnClosing;",
|
||||
"_window.FocusChanged += OnFocusChanged;",
|
||||
"_window.Move += _displayFramePacing.OnWindowMoved;",
|
||||
"_window.StateChanged += _displayFramePacing.OnWindowStateChanged;",
|
||||
"_window.FramebufferResize += OnFramebufferResize;",
|
||||
"_windowCallbacks = SilkWindowCallbackBinding.Create(",
|
||||
"new WindowCallbackTargets(",
|
||||
"OnLoad,",
|
||||
"OnUpdate,",
|
||||
"OnRender,",
|
||||
"OnClosing,",
|
||||
"OnFocusChanged,",
|
||||
"OnFramebufferResize),",
|
||||
"_displayFramePacing,",
|
||||
"_hostQuiescence);",
|
||||
"_windowCallbacks.Attach();",
|
||||
"_window.Run();");
|
||||
|
||||
string[] registrations =
|
||||
[
|
||||
"_window.Load += OnLoad;",
|
||||
"_window.Update += OnUpdate;",
|
||||
"_window.Render += OnRender;",
|
||||
"_window.Render += _displayFramePacing.OnFrameRendered;",
|
||||
"_window.Closing += OnClosing;",
|
||||
"_window.FocusChanged += OnFocusChanged;",
|
||||
"_window.Move += _displayFramePacing.OnWindowMoved;",
|
||||
"_window.StateChanged += _displayFramePacing.OnWindowStateChanged;",
|
||||
"_window.FramebufferResize += OnFramebufferResize;",
|
||||
];
|
||||
foreach (string registration in registrations)
|
||||
Assert.Equal(1, CountOccurrences(body, registration));
|
||||
Assert.Equal(1, CountOccurrences(body, "SilkWindowCallbackBinding.Create("));
|
||||
Assert.Equal(1, CountOccurrences(body, "_windowCallbacks.Attach();"));
|
||||
Assert.DoesNotContain("_window.Load +=", body, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("_window.Update +=", body, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("_window.Render +=", body, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("_window.Closing +=", body, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -160,7 +154,11 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
"new AcDream.App.Rendering.RenderFrameInput(");
|
||||
Assert.DoesNotContain("FramebufferSize", render, StringComparison.Ordinal);
|
||||
AssertAppearsInOrder(focus, "if (!focused)", "_gameplayInputFrame?.EndMouseLook();");
|
||||
AssertAppearsInOrder(close, "=> CompleteShutdown();", "_shutdown.CompleteOrThrow();");
|
||||
AssertAppearsInOrder(
|
||||
close,
|
||||
"_hostQuiescence.StopAccepting();",
|
||||
"CompleteShutdown();",
|
||||
"_shutdown.CompleteOrThrow();");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -197,6 +195,11 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
Assert.Equal(stages.Length, CountOccurrences(manifest, "new ResourceShutdownStage("));
|
||||
foreach (string stage in stages)
|
||||
Assert.Equal(1, CountOccurrences(manifest, stage));
|
||||
AssertAppearsInOrder(
|
||||
manifest,
|
||||
"binding.Dispose();",
|
||||
"if (!binding.IsDisposalComplete)",
|
||||
"_windowCallbacks = null;");
|
||||
AssertAppearsInOrder(
|
||||
dispose,
|
||||
"CompleteShutdown();",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue