pub struct Streams { /* private fields */ }Expand description
The fleet’s stream table. Cheap to clone; every clone in a process is the same table, the same driver and the same wakers.
Implementations§
Source§impl Streams
impl Streams
Sourcepub fn with_group(
name: &str,
capacity: u16,
node: NodeId,
incarnation: Incarnation,
spec: StreamSpec,
access: GroupAccess,
) -> Result<Self>
pub fn with_group( name: &str, capacity: u16, node: NodeId, incarnation: Incarnation, spec: StreamSpec, access: GroupAccess, ) -> Result<Self>
Open only a dedicated group-shared stream table. The supplied identity does not change any Fleet policy or publish other shared resources.
Sourcepub fn prepare_group(
name: &str,
capacity: u16,
spec: StreamSpec,
access: GroupAccess,
) -> Result<()>
pub fn prepare_group( name: &str, capacity: u16, spec: StreamSpec, access: GroupAccess, ) -> Result<()>
Initialize/validate transport before its inbox becomes joinable.
Sourcepub fn node_dead_in_group(
name: &str,
capacity: u16,
spec: StreamSpec,
node: NodeId,
incarnation: Incarnation,
access: GroupAccess,
) -> Result<()>
pub fn node_dead_in_group( name: &str, capacity: u16, spec: StreamSpec, node: NodeId, incarnation: Incarnation, access: GroupAccess, ) -> Result<()>
Recover an exact incarnation under its caller-held Link lane lock.
Sourcepub fn node_dead_in_shm(
name: &str,
fleet_capacity: u16,
spec: StreamSpec,
node: NodeId,
incarnation: Incarnation,
) -> Result<bool>
pub fn node_dead_in_shm( name: &str, fleet_capacity: u16, spec: StreamSpec, node: NodeId, incarnation: Incarnation, ) -> Result<bool>
Report one confirmed death to an existing shared table without claiming an endpoint, superseding a node, or installing a driver. Returns false when the table does not exist; never creates it then.
Sourcepub fn new(fleet: Arc<Fleet>, incarnation: Incarnation) -> Result<Self>
pub fn new(fleet: Arc<Fleet>, incarnation: Incarnation) -> Result<Self>
Open the fleet’s table as this process’s incarnation. Every side
this process claims is stamped with it, and Streams::node_dead
for the same node and incarnation is what ends those sides.
Sourcepub fn with_spec(
fleet: Arc<Fleet>,
incarnation: Incarnation,
spec: StreamSpec,
) -> Result<Self>
pub fn with_spec( fleet: Arc<Fleet>, incarnation: Incarnation, spec: StreamSpec, ) -> Result<Self>
Open the table spec names. Independent specs are independent
tables: separate segments, separate lanes and rings, separate
epochs, and a reset_all on one leaves the others alone. A process
may hold as many as it has specs, but each under one incarnation.
Sourcepub fn readiness(&self) -> Result<Readiness>
pub fn readiness(&self) -> Result<Readiness>
A descriptor that becomes readable when something among this process’s streams may have changed, for a runtime that parks on descriptors rather than on wakers.
Edge-triggered and coalescing: drain it, then re-try the non-blocking calls on the streams you hold. It is what makes this table usable from a foreign event loop — an embedded runtime, a reactor of its own — without a thread or a descriptor per stream.
One per table: a second caller is refused rather than handed a descriptor whose signals the first would drain.
Sourcepub fn create(&self) -> Result<(Endpoint, Ticket)>
pub fn create(&self) -> Result<(Endpoint, Ticket)>
Take a slot in this process’s lane. The endpoint is side A; the ticket names side B and is what the other end opens.
Sourcepub fn open(&self, ticket: Ticket) -> Result<Endpoint>
pub fn open(&self, ticket: Ticket) -> Result<Endpoint>
Hold the side a ticket names. Each side can be held once per stream.
Sourcepub fn rearm(&self, id: StreamId) -> Result<()>
pub fn rearm(&self, id: StreamId) -> Result<()>
Clear a stream for another exchange, and let its far side be opened again — by any process.
A slot created and released per exchange pays for both every time: two compare-and-swaps, a reset, and a ring nobody has touched since it was last used, so cold in cache and absent from the TLB. A creator that keeps its slots between exchanges calls this instead. Its own claim stands and the generation does not move, so the ticket stays valid; the directions go back to nothing, and the far side changes hands.
The far side has to have let go, and the table is what says so. Its halves raise their flags as they drop and its claim is released after them, so a claim that reads released belongs to a process that can no longer touch the slot. That is the whole handshake — no message, no flag to race with — and it is why the slot belongs to its creator rather than to a pair: once reopened, whichever process the next exchange is addressed to opens it.
Ok: re-armed; the next ticket written for it can be opened.Error::WouldBlock: the far side still holds it. Not yet — try another slot.Error::Stale: let it go. The address no longer names this stream, the far side died, or it never opened this exchange at all — and a side nobody opened may still be opened late by whoever the last ticket went to, so it is not safe to hand to anyone else. Dropping the endpoint empties the slot, and a late open is then refused as stale.
The far side’s owner goes back to what Streams::create writes for
nobody before its claim opens. A death report reads the claim first and
the owner after it, so without this a report about the process that
just let go could land on the one that opens next.
The caller owns the ordering. Whoever re-arms must do it before telling the other side that a new exchange has begun, so that the message announcing the exchange is what publishes the cleared state.
Sourcepub fn offer(&self, ticket: Ticket, to: NodeId) -> Result<()>
pub fn offer(&self, ticket: Ticket, to: NodeId) -> Result<()>
Tell node’s process that side B of this stream is its to take:
the slot is put in that node’s offer bitmap and its doorbell rung.
Discovery only; the ticket may just as well travel by any other
channel. An offer is seen once, by that node, through
Streams::take_offer and its waiting forms.
Sourcepub fn take_offer(&self) -> Option<Ticket>
pub fn take_offer(&self) -> Option<Ticket>
The next stream offered to this node, if any. A stream that ended between the offer and now is skipped.
Sourcepub fn take_offer_timeout(&self, timeout: Duration) -> Result<Option<Ticket>>
pub fn take_offer_timeout(&self, timeout: Duration) -> Result<Option<Ticket>>
The same wait, bounded: None is the timeout and nothing else.
A worker whose shutdown must be observed waits this way rather
than parking on the next request forever.
Sourcepub fn blocking_take_offer(&self) -> Result<Ticket>
pub fn blocking_take_offer(&self) -> Result<Ticket>
Park the thread until a stream is offered to this node.
Sourcepub fn poll_take_offer(&self, cx: &mut Context<'_>) -> Poll<Result<Ticket>>
pub fn poll_take_offer(&self, cx: &mut Context<'_>) -> Poll<Result<Ticket>>
Readiness for a task: the next offer, or the waker is registered
and Pending comes back.
Sourcepub fn owners(&self) -> Vec<(NodeId, Incarnation)>
pub fn owners(&self) -> Vec<(NodeId, Incarnation)>
Every process generation that still holds a side of a stream here.
The mirror of Pool::owners, and for the same caller: a supervisor
that has to decide what to report dead after losing its own record.
It says who is in the table, never who is alive.
Sourcepub fn node_dead(&self, node: NodeId, incarnation: Incarnation)
pub fn node_dead(&self, node: NodeId, incarnation: Incarnation)
A confirmed death, reported by whoever supervises processes: every
side that incarnation of node held, in any lane, is finished. Its
unfinished writes become resets and its reads are gone, so a holder
of the other side wakes with an error; that holder keeps the slot
until it drops its handles, and only then is the slot reused. A
report for another incarnation of the same node touches nothing.
Sourcepub fn supersede(&self)
pub fn supersede(&self)
This process took over its node from an earlier life: every side that
any other incarnation of this node held, in any lane, is finished, as
Streams::node_dead finishes one. The node id is inherited and the
incarnation is not, so what the node left behind is told apart from
this process’s own by the stamp alone — no report from a supervisor
is needed.
Call it once, before this process creates or opens anything. It is sound only where a node is handed on after its holder is gone; a node given to a second process while the first still runs would have that process’s streams ended under it.