Expand description
Shared<T>: mutable state that more than one task may reach.
The Language Card names this type in the sentence that keeps a vector out
of a task: “finish it as an array or wrap mutable state in Shared or
another synchronized type.” ADR 0008 makes it the one value that crosses a
task boundary by sharing rather than by copying, which is the reason the
type exists.
let metrics = Shared(Metrics(requests: 0, failures: 0))
metrics.lock(fn(var value) { value.record(failed) })There is no get and no set. Every access is a scoped SharedCell::lock,
so a read-modify-write cannot be written as two operations that race: the
read, the modification, and the write are one call with the lock held for
all three.
What the cell holds is a Transfer, not a Value: the wrapped value
must be task-safe, a task-safe value is exactly one a Transfer can carry,
and a Transfer is the only form two threads can both address. Each lock
therefore converts the cell’s contents into the locking task’s own
Value and converts back what the closure leaves — the same copy the
task-safety rule already demands at every other boundary.
§Cycles
A cell may hold another cell, including itself, and ADR 0011 says plainly
that nothing reclaims such an Arc cycle: cells outlive every task that
holds one, so collecting a cycle among them needs a collector that stops
every thread, which the per-task collector rules out by design. The ADR’s
amendment picks a narrower, cheaper policy: lock rejects the one shape
of cycle it can see for free — the cell ending up holding a handle to
itself — and leaves everything wider as a documented, accepted leak. See
Transfer::reaches and direct_cycle.
Structs§
- Shared
Cell - The storage a
Shared<T>value addresses.