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
|
|
@ -16,7 +16,7 @@ audit.
|
|||
|
||||
- [x] A — freeze construction/callback/shutdown order and delete proven dead or
|
||||
test-facade residue.
|
||||
- [ ] B — make native-window callback intake an explicit reversible owner and
|
||||
- [x] B — make native-window callback intake an explicit reversible owner and
|
||||
define host-quiescence failure semantics.
|
||||
- [ ] C — extract live-session host/reset/binding callbacks and verify the
|
||||
embedded skill formula against named retail.
|
||||
|
|
@ -220,20 +220,31 @@ Add a focused reversible binding equivalent to:
|
|||
```csharp
|
||||
internal sealed class SilkWindowCallbackBinding : IDisposable
|
||||
{
|
||||
public static SilkWindowCallbackBinding Attach(
|
||||
public static SilkWindowCallbackBinding Create(
|
||||
IWindow window,
|
||||
WindowCallbackTargets targets,
|
||||
DisplayFramePacingController pacing);
|
||||
|
||||
public void Attach();
|
||||
}
|
||||
```
|
||||
|
||||
`WindowCallbackTargets` is a fixed typed set for Load, Update, Render, Closing,
|
||||
FocusChanged, and FramebufferResize. It is not a general callback list. Attach
|
||||
rolls back in reverse order if any registration fails; Dispose detaches in
|
||||
reverse registration order, is idempotent/reentrant-safe, and makes later
|
||||
window events inert. The separate pacing Render callback remains ordered after
|
||||
main Render. Every callback first checks the shared no-throw host-quiescence
|
||||
gate, so a failed physical unsubscribe cannot re-enter a retired owner.
|
||||
FocusChanged, and FramebufferResize. It is not a general callback list. The
|
||||
binding is published into its lifetime slot after `Create` and before `Attach`
|
||||
begins, so even an attach failure plus rollback failure retains a cleanup owner.
|
||||
Attach treats the current edge as possibly acquired before calling a custom
|
||||
event add accessor and rolls back in reverse order if registration fails.
|
||||
The explicit lifecycle state monitor is released around every external event
|
||||
accessor; external cleanup waits for Attaching/Detaching to converge, while a
|
||||
gate-owned reentrant cleanup reports typed deferred completion instead of
|
||||
deadlocking or falsely succeeding. Dispose detaches in reverse registration
|
||||
order, joins concurrent callers, is idempotent/reentrant-safe, and makes later
|
||||
window events inert. `GameWindow` clears the retained slot only after terminal
|
||||
disposal. The separate pacing Render callback remains ordered after main Render.
|
||||
Every callback enters the shared no-throw host-quiescence monitor, so external
|
||||
shutdown drains an admitted callback, Closing can stop reentrantly, and a failed
|
||||
physical unsubscribe cannot re-enter a retired owner.
|
||||
|
||||
### 3.2 Input owners
|
||||
|
||||
|
|
@ -416,6 +427,17 @@ tests and the complete App suite (2,991 pass / 3 intentional skips) pass.
|
|||
- Add post-detach silence, failure-after-Nth-attach, repeated/reentrant Dispose,
|
||||
callback-during-detach, and persistent physical-detach tests.
|
||||
|
||||
Result: one fixed typed binding now owns the exact nine Silk edges, including
|
||||
the two ordered Render callbacks. Create/publish/Attach and the explicit
|
||||
lifecycle state preserve cleanup ownership across partial event-accessor
|
||||
failure, rollback failure, concurrent or reentrant shutdown, and condition
|
||||
wakeups. The shared host gate drains admitted callbacks and makes failed
|
||||
physical detach logically inert. Three corrected-diff review loops are clean;
|
||||
54 focused tests, the App suite (3,027 pass / 3 intentional skips), and the full
|
||||
Release suite (7,386 pass / 5 intentional skips) pass. No connected gate was
|
||||
required because this checkpoint changes ownership only and preserves the
|
||||
frozen callback behavior.
|
||||
|
||||
### C — live-session host and skill formula
|
||||
|
||||
- Extract selection/entry/reset/binding factories around the existing canonical
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue