Skip to content

feat: wire ElementId into Counter/Register/Map + Map<Element> with recursive merge#14

Merged
vieiralucas merged 5 commits into
mainfrom
nested-map
Jun 3, 2026
Merged

feat: wire ElementId into Counter/Register/Map + Map<Element> with recursive merge#14
vieiralucas merged 5 commits into
mainfrom
nested-map

Conversation

@vieiralucas

@vieiralucas vieiralucas commented Jun 2, 2026

Copy link
Copy Markdown
Member

What

  • Counter / Register / Map now opaque; carry an ElementId set at *_create. New accessors: counter_id, register_id, map_id.
  • Map slot value is Element (was Scalar). map_set / map_get / map_delete / map_merge updated.
  • map_merge per-slot rule:
    • both alive, same composite kind, same id → element_merge (recursive, in-place).
    • otherwise → LWW on slot stamp; scalar winner is scalar_dup'd into dst arena.
  • LWW with a composite winner host_aborts (cross-arena pointer would dangle). Deterministic id derivation in PR 5 keeps this path unreachable in normal use.
  • element.h breaks the map.h include cycle via typedef struct Map Map; forward decl.
  • elementid.h header guard fix — #define was missing.
  • Death test test_map_abort.c exercises the abort; Makefile target inverts the exit (! ./test_map_abort).

Summary by cubic

Switch Map to store Element values and wire ElementId through Counter/Register/Map to enable recursive merges of same-id composites. Recursive merges advance the slot stamp; any LWW path that hits a composite aborts to avoid cross-arena pointers and stamp-dependent divergence.

  • New Features

    • Counter/Register/Map are opaque and carry an ElementId set at create; added counter_id, register_id, map_id.
    • Map stores Element; map_set/map_get/map_delete/map_merge updated. Scalars are duped into the dst arena; composites are pointers.
    • map_merge: same composite kind + same id → recursive element_merge, then set slot stamp to max(dst, src); otherwise LWW on the slot. Any LWW path with a composite now host_aborts.
    • Broke the element.hmap.h include cycle via forward decl; fixed elementid.h header guard; updated header docs (incl. map_get returns Element). Added death test test_map_abort and a Makefile target.
  • Migration

    • Constructors now take ids: counter_create(arena, id), register_create(arena, id, value, stamp), map_create(arena, id).
    • Map API uses Element: wrap scalars with element_scalar(...) when calling map_set; map_get returns Element.
    • For nested composites, derive deterministic ElementIds per slot so replicas share ids and merges recurse.

Written for commit 8f1672b. Summary will update on new commits.

Review in cubic

…cursive merge

- Counter/Register/Map opaque, carry an ElementId set at create.
- Map slot value is Element (was Scalar). map_set/get/delete/merge updated.
- map_merge same-key path: same composite kind + same id -> element_merge
  (recursive). Otherwise LWW on slot stamp.
- LWW with composite displacement host_aborts (cross-arena pointer would
  dangle). Deterministic id derivation in PR 5 keeps the path unreachable
  in normal use.
- element.h breaks the map.h cycle via forward decl typedef struct Map.
- elementid.h header guard fixed (#define was missing).
- Death test test_map_abort.c exercises the abort; Makefile inverts exit.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 16 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread map.c Outdated
Comment thread map.c
Comment thread map.h
… LWW when src wins

- Recursive same-id merge now sets dst slot stamp to max(dst, src). Without
  this, a later slot-level op on dst could flip the slot using a stamp src
  has already moved past, and replicas diverge.
- LWW fallthrough no longer aborts on composite src that LOSES the stamp
  comparison. The abort guard is for the cross-arena displacement hazard
  (src wins); when src loses, dst keeps its slot and nothing dangles.
- Tombstone branch in the fallthrough takes its own continue to keep the
  remaining LWW-vs-abort flow flat.
Hitting LWW with a composite means id derivation is broken or types
diverged at this key. That is a programmer error regardless of which
side's stamp wins; skipping the abort when src loses by stamp made the
crash stamp-dependent, which would let the same broken state crash one
replica and silently pass on another.

Restore unconditional abort; drop the now-misleading "src loses does not
abort" regression test.
@vieiralucas

Copy link
Copy Markdown
Member Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 3, 2026

Copy link
Copy Markdown

@cubic-dev-ai review

@vieiralucas I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 16 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread map.h
@vieiralucas vieiralucas merged commit 87fb142 into main Jun 3, 2026
2 checks passed
@vieiralucas vieiralucas deleted the nested-map branch June 3, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant