pub struct Loopback { /* private fields */ }Expand description
The aggregate handle: one value implementing all twelve port traits by delegating to the six role handles it holds.
A face is built over one value implementing at least the port traits its
interface needs, and a generated Client is commonly bound over
SignalReader + EventSource + Caller at once, which no single role handle
satisfies. That is what an aggregate is for (ADR-0021 decision 12). Pass it
by value, or as &mut under the forwarding impls of ADR-0021 decision 11.
Implementations§
Source§impl Loopback
impl Loopback
Sourcepub const SLOTS: usize = 16
pub const SLOTS: usize = 16
The number of calls the runtime holds at once. A call holds its slot from its send until one of these reclaims it:
Caller::forget, or the drop of the caller handle that sent it, while it is settled or still waiting for a handler;- its settlement, when it was forgotten while a handler held it;
- the drop of the handler that held it unsettled, when it was forgotten.
So a settled call keeps its slot until it is forgotten, and a claimed
call keeps its slot after its forget until it is settled or its
handler is dropped. With every slot taken, Caller::command and
Caller::query answer SendError::Busy, on every caller handle,
because the table is the runtime’s.
Sixteen is a small bound, chosen so that a test reaches it in a few sends and a program that never forgets a call finds out at once rather than after its memory grows. The loopback has no catalog descriptor to size a byte budget from (story E16.2), so the slot count is its only bound (note F-9 of the async face design).
The generated async client’s future (story E11.21) forgets its call
when it leaves the waiting phase: in the poll that takes the outcome,
at the call’s deadline, and on drop while the call is still waiting.
So a program that calls through the generated face holds one slot per
call in flight. A program that sends through the Caller port
directly must forget each correlation itself once it has read the
outcome, or drop the caller handle, which forgets that handle’s calls;
otherwise it gets SendError::Busy from its seventeenth call on.
Sourcepub fn new(catalog: CatalogRef) -> Self
pub fn new(catalog: CatalogRef) -> Self
A runtime attached to catalog, with an empty store and its clock at
Timestamp 0.
The catalog is carried, not checked: see the crate documentation.
Sourcepub fn split(self) -> Handles
pub fn split(self) -> Handles
Hands out the six role handles this aggregate holds. Every one of them
keeps the same store, so a value published through writer is read
through reader.
Sourcepub fn reader(&self) -> ReaderHandle
pub fn reader(&self) -> ReaderHandle
An additional reader handle on the same store.
Sourcepub fn writer(&self) -> WriterHandle
pub fn writer(&self) -> WriterHandle
An additional writer handle on the same store, with its own staging area and its own per channel sequence counters.
Sourcepub fn source(&self) -> SourceHandle
pub fn source(&self) -> SourceHandle
An additional event source on the same store, with its own subscription set and its own queue.
Sourcepub fn sink(&self) -> SinkHandle
pub fn sink(&self) -> SinkHandle
An additional event sink on the same store, with its own sequence counter.
Sourcepub fn caller(&self) -> CallerHandle
pub fn caller(&self) -> CallerHandle
An additional caller on the same store, with its own sequence counter. Two callers on one provider therefore never collide on a sequence number (driftsys/ridl#308).
Sourcepub fn handler(&self) -> HandlerHandle
pub fn handler(&self) -> HandlerHandle
An additional handler on the same store.
Every handler draws from the one queue of waiting calls, filtered by what it has served: a handler that has served nothing is presented every waiting call, and one that has served members is presented only those. A claim belongs to the handler it was presented to.
Sourcepub fn advance(&mut self, by: Duration)
pub fn advance(&mut self, by: Duration)
Advances the clock by by.
The clock is a counter this method moves and nothing else moves. It never reads wall-clock time, so a round trip over this runtime produces the same timestamps on every run and on every machine. It saturates rather than overflowing.
§Panics
When by is negative. A clock that ran backwards would stamp an
envelope before one already stamped.
Sourcepub fn provision_fixed(
&mut self,
iface: InterfaceNo,
ord: Ordinal,
bytes: &[u8],
)
pub fn provision_fixed( &mut self, iface: InterfaceNo, ord: Ordinal, bytes: &[u8], )
Supplies the value of a fixed (ridl §8), which is provisioned into a
runtime rather than published by application code.
Until a fixed is provisioned, reading it answers
ReadError::Contract(Contract::UnknownInteraction): the loopback holds
no value and, having no member table, cannot say anything narrower.
Sourcepub fn fail_next_settle(&mut self)
pub fn fail_next_settle(&mut self)
Makes the next Handler::settle on this runtime fail with
SettleError::TooLarge and record no outcome.
This is the one fault this runtime injects, and the one place a
SettleError other than UnknownClaim comes from. It exists because
the generated dispatch counts a claim only once the handler has
accepted its settlement, and nothing else in an in-process runtime can
make that path fail.
Trait Implementations§
Source§impl Attached for Loopback
impl Attached for Loopback
Source§fn catalog(&self) -> &CatalogRef
fn catalog(&self) -> &CatalogRef
Source§impl Caller for Loopback
impl Caller for Loopback
Source§fn command(
&mut self,
iface: InterfaceNo,
ord: Ordinal,
args: &[u8],
) -> Result<Correlation, SendError>
fn command( &mut self, iface: InterfaceNo, ord: Ordinal, args: &[u8], ) -> Result<Correlation, SendError>
Source§fn query(
&mut self,
iface: InterfaceNo,
ord: Ordinal,
args: &[u8],
) -> Result<Correlation, SendError>
fn query( &mut self, iface: InterfaceNo, ord: Ordinal, args: &[u8], ) -> Result<Correlation, SendError>
Source§fn ack(&mut self, c: Correlation) -> Option<Result<(), CallError>>
fn ack(&mut self, c: Correlation) -> Option<Result<(), CallError>>
Ok(()) when accepted, Err(CallError::Contract(_)) when rejected,
Err(CallError::Transport(Transport::Corrupt)) when the provider could
not read the command’s argument bytes,
Err(CallError::Transport(Transport::Busy)) when the providing runtime
refused the command at admission, and
Err(CallError::Transport(Transport::Undelivered)) when no
acknowledgment came within the bound. None while unknown, and always
None for a query’s correlation. Read moreSource§fn reply(
&mut self,
c: Correlation,
out: &mut [u8],
) -> Result<Option<Result<usize, CallError>>, ReadError>
fn reply( &mut self, c: Correlation, out: &mut [u8], ) -> Result<Option<Result<usize, CallError>>, ReadError>
out and their length, or the error. Ok(None) while unknown.
ReadError::Short does not consume the reply. Read moreSource§fn forget(&mut self, c: Correlation)
fn forget(&mut self, c: Correlation)
Source§impl CoherentSignals for Loopback
impl CoherentSignals for Loopback
Source§fn read_coherent(
&self,
iface: InterfaceNo,
ords: &[Ordinal],
out: &mut [u8],
samples: &mut [RawSample],
) -> Result<usize, ReadError>
fn read_coherent( &self, iface: InterfaceNo, ords: &[Ordinal], out: &mut [u8], samples: &mut [RawSample], ) -> Result<usize, ReadError>
ords from one publication. Copies the values
into out one after another, writes one RawSample for each ordinal
into samples in the order of ords, and returns the number of bytes
written to out. Read moreSource§impl EventSink for Loopback
impl EventSink for Loopback
Source§fn raise(
&mut self,
iface: InterfaceNo,
ord: Ordinal,
bytes: &[u8],
) -> Result<(), RaiseError>
fn raise( &mut self, iface: InterfaceNo, ord: Ordinal, bytes: &[u8], ) -> Result<(), RaiseError>
Source§impl EventSource for Loopback
impl EventSource for Loopback
Source§fn subscribe(
&mut self,
iface: InterfaceNo,
ords: &[Ordinal],
) -> Result<(), SubscribeError>
fn subscribe( &mut self, iface: InterfaceNo, ords: &[Ordinal], ) -> Result<(), SubscribeError>
Source§fn unsubscribe(&mut self, iface: InterfaceNo, ords: &[Ordinal])
fn unsubscribe(&mut self, iface: InterfaceNo, ords: &[Ordinal])
Source§impl FixedReader for Loopback
impl FixedReader for Loopback
Source§fn read_fixed(
&self,
iface: InterfaceNo,
ord: Ordinal,
out: &mut [u8],
) -> Result<usize, ReadError>
fn read_fixed( &self, iface: InterfaceNo, ord: Ordinal, out: &mut [u8], ) -> Result<usize, ReadError>
out and returns its
length.Source§impl Handler for Loopback
impl Handler for Loopback
Source§fn serve(
&mut self,
iface: InterfaceNo,
ords: &[Ordinal],
) -> Result<(), ServeError>
fn serve( &mut self, iface: InterfaceNo, ords: &[Ordinal], ) -> Result<(), ServeError>
Source§fn next_claim(&mut self, out: &mut [u8]) -> Result<Option<Claim>, ReadError>
fn next_claim(&mut self, out: &mut [u8]) -> Result<Option<Claim>, ReadError>
out. Ok(None)
when no call is waiting. ReadError::Short does not consume the call.Source§fn settle(
&mut self,
claim: ClaimId,
outcome: Result<&[u8], CallError>,
) -> Result<(), SettleError>
fn settle( &mut self, claim: ClaimId, outcome: Result<&[u8], CallError>, ) -> Result<(), SettleError>
CallError::Contract when the arguments break their typl
constraints, a require clause fails, or an ensure clause fails,
and CallError::Transport(Transport::Corrupt) when the argument
bytes fail the structure check.Source§impl ScannableSignals for Loopback
impl ScannableSignals for Loopback
Source§fn generation(&self, iface: InterfaceNo) -> u64
fn generation(&self, iface: InterfaceNo) -> u64
Source§fn scan(&self, marks: &mut [Watermark], out: &mut [Changed]) -> usize
fn scan(&self, marks: &mut [Watermark], out: &mut [Changed]) -> usize
out, interface by interface, in the order of
marks, and updates marks. An interface’s changes are written all
together or not at all: when they do not fit in the rest of out,
none of them is written, that interface’s mark is not updated, and
scan returns the number of entries written so far. Read moreSource§impl SignalReader for Loopback
impl SignalReader for Loopback
Source§impl SignalWriter for Loopback
impl SignalWriter for Loopback
Source§fn set(
&mut self,
iface: InterfaceNo,
ord: Ordinal,
bytes: &[u8],
) -> Result<(), WriteError>
fn set( &mut self, iface: InterfaceNo, ord: Ordinal, bytes: &[u8], ) -> Result<(), WriteError>
Source§fn invalidate(
&mut self,
iface: InterfaceNo,
ord: Ordinal,
) -> Result<(), WriteError>
fn invalidate( &mut self, iface: InterfaceNo, ord: Ordinal, ) -> Result<(), WriteError>
Cause::Declared.Source§fn touch(&mut self, iface: InterfaceNo, ord: Ordinal) -> Result<(), WriteError>
fn touch(&mut self, iface: InterfaceNo, ord: Ordinal) -> Result<(), WriteError>
Source§fn commit(&mut self)
fn commit(&mut self)
WriteError::Detached on a later set, invalidate or
touch, never from that commit. What becomes of the changes staged
before a commit whose runtime has already detached is not fixed here.