pub struct Orbital<T: CellType> { /* private fields */ }Expand description
One cell, typed. Cheap to clone; every clone is the same place.
Implementations§
Source§impl<T: CellType> Orbital<T>
impl<T: CellType> Orbital<T>
pub fn id(&self) -> CellId
pub fn load(&self) -> Result<T>
pub fn store(&self, value: T) -> Result<()>
Sourcepub fn version(&self) -> Result<u32>
pub fn version(&self) -> Result<u32>
The write count, the thing Self::wait_changed waits on. Take it
before reading the value, and the wait misses nothing in between.
Sourcepub fn wait_changed(&self, since: u32) -> Result<u32>
pub fn wait_changed(&self, since: u32) -> Result<u32>
Park until the cell has been written since since, then return the
count now. Coalescing: ten writes while parked wake the caller once,
and Self::load gives the latest. A released cell wakes every waiter
with Error::Stale. Blocking; an async runtime wraps it.
Sourcepub fn compare_exchange(&self, current: T, new: T) -> Result<Result<T, T>>
pub fn compare_exchange(&self, current: T, new: T) -> Result<Result<T, T>>
Store new only if the cell still holds current. Ok(Ok(previous))
on success, Ok(Err(actual)) when it held something else.
Sourcepub fn wait_changed_until(
&self,
since: u32,
interrupt: &AtomicBool,
) -> Result<Option<u32>>
pub fn wait_changed_until( &self, since: u32, interrupt: &AtomicBool, ) -> Result<Option<u32>>
Self::wait_changed, but a second word can end it. The waiter
still parks until something wakes it; interrupt is what tells it
which kind of wake arrived. Ok(Some(count)) is a write,
Ok(None) is the interrupt.
This is the shape a caller needs when the wait may outlive its
reason — a process that has to shut down while a script waits on a
cell nothing will write again. It is not a timeout: nothing here
measures time, and a wait nobody interrupts is
Self::wait_changed exactly.
The canceller sets interrupt and then calls
Self::wake_waiters, in that order. Set-then-wake is what closes
the window: a waiter that had already parked is released by the
wake, and one that had not yet parked sees the flag instead.
Sourcepub fn wake_waiters(&self) -> Result<()>
pub fn wake_waiters(&self) -> Result<()>
Wake everyone parked on this cell without writing to it. On its own
this changes nothing — a waiter re-checks the count, finds it where
it was and parks again — so it is only useful after the word the
waiter also watches has been set. See Self::wait_changed_until.
Source§impl Orbital<i64>
impl Orbital<i64>
Sourcepub fn fetch_add(&self, by: i64) -> Result<i64>
pub fn fetch_add(&self, by: i64) -> Result<i64>
Add by (negative to subtract) and return the value after.
pub fn fetch_sub(&self, by: i64) -> Result<i64>
Sourcepub fn add_until(&self, by: i64, limit: i64) -> Result<Claim>
pub fn add_until(&self, by: i64, limit: i64) -> Result<Claim>
Add up to by while the value stays at or under limit, in one
compare-and-swap, and say what was taken.
This is the operation a fleet needs to divide a fixed amount of work
between processes that cannot see each other. fetch_add followed by
a test cannot do it: the add lands before the caller learns it went
too far, so N callers overshoot by up to N-1 between them. Here the
bound is decided inside the swap, so the value never passes
limit however many callers race, and the one that finds less than
by left takes the remainder instead of being turned away.
Taking more than one at a time is how the cost comes down: the
contended word is touched once per claim rather than once per unit.
limit is the ceiling for the total, never for a single call.
Overflow needs no separate guard: a result that cannot pass limit
cannot pass i64::MAX either.
A claim is not a lease. What this hands back is gone from the
total the moment the swap lands, and nothing gives it back: a caller
that takes a hundred, does forty and then dies leaves sixty that
nobody will ever do, while the count says all hundred were taken. So
by is not only a speed dial, it is the exposure — the most one
death can lose. It is the same trade a database sequence makes with
its cache size, and it leaves the same kind of gap. Work that must
not be lost wants a lease whose owner notices a death, which is
orbit-pool, not a counter.