Expand description
SharedStringArena - append-only position-independent string
pool backed by an MMF.
§Why this exists
Variable-length strings can’t be stored inline in fixed-size
slots (SharedHashMap, SharedVec, etc.) without padding waste or
truncation. The natural cross-process solution is a shared byte
arena: every process maps the same file at (potentially)
different base addresses, and string references are
position-independent (offset, len) pairs. Adding
mmap_base + offset in any process resolves to the same bytes.
§Layout
+---------------------------+
| ArenaHeader (64B) |
| magic, capacity_bytes |
| used_bytes: AtomicU64 |
+---------------------------+
| bytes[0 .. capacity] |
+---------------------------+§Protocol
intern(s):
offset = used_bytes.fetch_add(len).- If
offset + len > capacity, rollback withfetch_sub(len)and returnFull. (Note: the rollback is best-effort; if two threads race-overflow simultaneously, both fetch_subs leave the counter deterministic without “losing” bytes.) - Memcpy
s.bytes()intoarena[offset..offset+len]. - Return
StringRef { offset, len }.
get(r):
- Bounds-check
r.offset + r.len <= used_bytes(sanity), then return&arena[r.offset..r.offset+r.len]as a&str.
§Concurrency
Concurrent interners get distinct slices via fetch_add. Once
the bytes are written, they are never moved (append-only). A
reader holding a StringRef can always resolve it correctly,
provided their get happens AFTER the interner returned the
ref (which is the natural happens-before edge: the interner
does the write, then makes the ref visible to the reader).
§Deduplication
Not provided here. For dedup, layer a SharedHashMap<u64 hash, StringRef> over the arena and consult it before each intern.
§No deletion
Append-only. The whole arena is reclaimed via clear (callers
must ensure no concurrent readers); fine-grained deletion
requires a free-list / compaction protocol that defeats the
point of an arena.
Structs§
- Arena
Header - Shared
String Arena - String
Ref - Position-independent reference to a string in a SharedStringArena.
Encoded as a
u64(offset:u32, len:u32) for stable cross-process passing (the same u64 resolves to the same bytes in every process that maps the arena).