Skip to main content

Orbital

Struct Orbital 

Source
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>

Source

pub fn id(&self) -> CellId

Source

pub fn load(&self) -> Result<T>

Source

pub fn store(&self, value: T) -> Result<()>

Source

pub fn swap(&self, value: T) -> Result<T>

Replace the value and return what it was.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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

pub fn release(self) -> Result<()>

Give the cell back; this and every other handle to it go stale.

Source§

impl Orbital<i64>

Source

pub fn fetch_add(&self, by: i64) -> Result<i64>

Add by (negative to subtract) and return the value after.

Source

pub fn fetch_sub(&self, by: i64) -> Result<i64>

Source

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.

Source§

impl Orbital<u64>

Source

pub fn fetch_add(&self, by: u64) -> Result<u64>

Source

pub fn fetch_sub(&self, by: u64) -> Result<u64>

Source§

impl Orbital<f64>

Source

pub fn fetch_add(&self, by: f64) -> Result<f64>

Add by and return the value after. A compare-and-swap loop: floats have no fetch-add of their own.

Source§

impl Orbital<bool>

Source

pub fn set(&self) -> Result<bool>

Set the flag and return whether it was already set.

Source

pub fn clear(&self) -> Result<bool>

Clear the flag and return whether it was set.

Trait Implementations§

Source§

impl<T: Clone + CellType> Clone for Orbital<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<T> !RefUnwindSafe for Orbital<T>

§

impl<T> !UnwindSafe for Orbital<T>

§

impl<T> Freeze for Orbital<T>
where PhantomData<T>: Freeze,

§

impl<T> Send for Orbital<T>
where PhantomData<T>: Send,

§

impl<T> Sync for Orbital<T>
where PhantomData<T>: Sync,

§

impl<T> Unpin for Orbital<T>
where PhantomData<T>: Unpin,

§

impl<T> UnsafeUnpin for Orbital<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.