Repository navigation
Conversation
…ache flecs_emit_forward iterates the reachable cache of a relationship pair while it invokes observers. An observer that modified the cache (for example by changing a base and then instantiating it) rebuilt the cache array in place, so the loop read freed memory. An observer that modified or deleted a source of the cache left the cache entries, and the table record passed to the next observers, pointing to the previous table of the source. That asserted in debug builds, and read an invalid or freed table record in release builds. Once observers have been invoked, a rebuild of the cache allocates a new array instead of modifying the iterated one, and the iterated array is freed when the iteration is done. A change to a source increments the generation of the cache, which now also marks the iterators of the cache as changed. Until then the cached table records are used. After a change, the table record of the source is looked up in its current table before each observer (or each result of an observer with a fixed source) is invoked, and the remaining observers for the id are skipped if the source is no longer alive or no longer has it. Tests: up observers that instantiate a changed base, add to or remove from the base, delete a tag of the base or the base of the base (with the id recycled into the same table), two observers on the same id, propagation to an instance's own instances, and fixed source multi observers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A table's override refs are recomputed when the reachable cache generation of one of its (IsA, base) pairs changes. Invalidating the reachable cache does not increment the generation of a cache that is already invalid, so a generation recorded while the cache was invalid could stay the same after a later change to a base. When a base removed an inherited component, the override then copied from a base that no longer had it (assert in flecs_table_invoke_ctor, a crash in release builds). When a base added the component, the override copied the value of a base further up, or no value. The reachable cache of each base is now revalidated before its generation is compared or stored. This can rebuild the cache while events are forwarded, which is safe because a rebuild doesn't modify an array that is being iterated. Because the cache can't be revalidated in multithreaded mode, flecs_table_get_override no longer updates the shared override cache in that mode, and instead looks up the base the same way it already did for sparse components. Tests: a base and an intermediate base that remove or add the component, a three level chain, the override policy, ensure from a stage in readonly and multithreaded mode, OnSet when the override is removed, and an override created by an observer while the base changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on #2396, whose commit is included here; only the second commit is new.
A table's override refs are recomputed when the reachable cache generation of one of its (IsA, base) pairs changes. Invalidating the reachable cache doesn't increment the generation of a cache that is already invalid, so a generation recorded while the cache was invalid could stay the same after a later change to a base:
flecs_table_invoke_ctor, and crashes in release builds.The reachable cache of each base is now revalidated before its generation is compared or stored. That can rebuild the cache while events are forwarded, which is safe after #2396. Because the cache can't be revalidated in multithreaded mode,
flecs_table_get_overrideno longer updates the shared override cache in that mode, and looks up the base the same way it already did for sparse components.Tests:
Prefab.override_in_observer_after_base_changepasses on master. It guards the combination of the two commits.🤖 Generated with Claude Code