fix(grid): ~UIGridView unregisters from the GridData view registry
GridData::views (the N-view registry that replaced owning_view in #359) was only ever pruned by UIGridView::set_grid and by tp_dealloc -- and tp_dealloc's unregister is gated on data.use_count() <= 1 (the #251 pattern). When the C++ view outlives its Python wrapper, which is the normal case because the scene holds the last shared_ptr, that guard skips the unregister and the view's entry survives its own destruction as an expired weak_ptr. Entries therefore accumulated for the lifetime of a GridData, and markDirty() / markCompositeDirty() lock() every one of them on every entity move. Not a correctness bug (expired weak_ptrs lock to null and are skipped) but an unbounded leak on a hot path. ~UIGridView is the only place guaranteed to run exactly once per view, so the unregister belongs there. unregisterView already prunes expired entries, so no other change is needed. NO REGRESSION TEST: GridData::views has no Python observable, so the registry's size cannot be asserted from a test script. Adding one (e.g. a read-only GridData.view_count) is deliberately deferred to #361, which makes GridData a public type and reworks this area; the fix is landed now because the leak is on a hot path and the one-liner is unambiguous. Full suite green (324/324). closes #362
This commit is contained in:
parent
11f8394f9b
commit
461dcf7f29
2 changed files with 11 additions and 1 deletions
File diff suppressed because one or more lines are too long
|
|
@ -32,6 +32,16 @@ UIGridView::UIGridView()
|
|||
}
|
||||
|
||||
UIGridView::~UIGridView() {
|
||||
// #362: drop ourselves from the GridData's view registry. This is the only
|
||||
// place guaranteed to run exactly once per view: tp_dealloc's unregister is
|
||||
// gated on data.use_count() <= 1 (the #251 pattern), so a view that outlives
|
||||
// its Python wrapper -- the normal case, when the scene holds the last ref --
|
||||
// would otherwise leave an expired weak_ptr in `views` forever. markDirty()
|
||||
// walks that vector on every entity move.
|
||||
if (grid_data) {
|
||||
grid_data->unregisterView(this);
|
||||
}
|
||||
|
||||
// #348: release the persistent internal-Grid wrapper. Guard with
|
||||
// Py_IsInitialized() because this destructor may run during interpreter
|
||||
// shutdown (mirrors Animation::~Animation).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue