Add GetOrAdd and GetOrAddFunc to the single-component handle - #4
Merged
Conversation
Introduce a first-class get-or-create operation on Accessor[A]: - GetOrAdd(id, value) returns the interior pointer to the entity's component, adding value first if absent (eager). - GetOrAddFunc(id, make) does the same but builds the value lazily via make, which is called only on the miss path. Both return a non-nil *A valid until the next structural change, and the add honours the existing deferral rules: immediate at depth 0, deferred during an All() loop where the returned pointer is to a staged value the flush inserts, so writes through it survive into the store. Update the README's core concepts and "API at a glance" to list the new get-or-create pair. fixes #3
GetOrAdd's miss path previously inserted via applyAdd and then re-derived the interior pointer with a second map lookup. Have applyAdd return the pointer it just created so the lookup happens once; other callers ignore the return value.
4 tasks
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.
Summary
Adds a first-class get-or-create operation to the single-component handle (
Accessor[A]), as specified in #3:GetOrAdd(id, value) *A— returns the interior pointer to the entity's component, insertingvaluefirst if absent (eager).GetOrAddFunc(id, make) *A— same, but builds the value lazily viamake, which is called only on the miss path (nothing constructed on a hit).Both return a non-nil
*A, valid until the next structural change to the store (the same contract asGetand iteration).Design notes
The add honours the existing deferral model exactly as
Adddoes:Add's no-op), but a non-nil pointer to the unstored value is still returned to keep the "never nil" contract.All()loop: deferred. Because the result must remain a usable pointer for the rest of the loop, the value is staged off-store and the returned pointer points at it; the auto-flush inserts that same value, so writes made through the pointer during the loop survive into the store. No mutation touches the dense storage mid-iteration, so previously-yielded iteration pointers stay valid.Both methods delegate to a shared private
insertMissinghelper after the get-miss check, so the eager/lazy split is the only difference between them.Scope is the single-component handle only; the join handles (
Accessor2/Accessor3) are out of scope per the issue.Testing
New tests in
ecs_components_test.gocover: insert-on-miss (both variants), return-existing-without-overwrite,makenot called on hit, dead-entity returns non-nil without storing, deferred-during-iteration (mutation through the staged pointer lands after flush), and hit-path-during-iteration returning a live pointer.Verification (all clean):
Docs
Updated the README's "Core concepts" and "API at a glance" to list the new get-or-create pair.
fixes #3
✨ Content generated by Claude AI.