pub struct Dioring<B: IoBuf, E: EpochId + 'static = u64, C = (), R: IoBufMut = Vec<u8>, K: StampClock = InterruptStamps> { /* private fields */ }Expand description
dioring: B is the owned buffer type, E the epoch-id type, C the consumer’s
per-operation context, R the registered-buffer type, and K the clock it stamps failures with
(a TimeBase; InterruptStamps unless built with Dioring::with_clock).
The instance’s core and its Windows backend are drained on the thread pool (DI-D-53), so the
buffer, epoch-id, context and registered-buffer types cross to pool threads and must be Send;
the epoch-id type must also be Sync, because a failure’s suspect set is shared. An owned write
needs only B: IoBuf, so a write-only type serves; an owned read needs B: IoBufMut
(DI-D-17).
Implementations§
Source§impl<B, E, C, R> Dioring<B, E, C, R>
impl<B, E, C, R> Dioring<B, E, C, R>
Sourcepub fn new(
setup: Setup<'_, '_, E, R>,
) -> Result<(Self, LineageHandle), SetupError<E, R>>
pub fn new( setup: Setup<'_, '_, E, R>, ) -> Result<(Self, LineageHandle), SetupError<E, R>>
Build an instance, make the ring’s registrations, and wire its delivery. Blocks until both
registrations have completed. Returns the instance with a handle to its default lineage
(DI-D-40). Failures are stamped with InterruptStamps; see Dioring::with_clock for
another clock.
§Errors
A SetupError handing back what it was given, for a duplicate target key, a provider
domain named twice, or a ring that could not be created, make a registration, or be wired
to deliver its completions. The checks that need no ring run first, so a refusal for
either of the first two creates nothing.
Source§impl<B, E, C, R, K> Dioring<B, E, C, R, K>
impl<B, E, C, R, K> Dioring<B, E, C, R, K>
Sourcepub fn with_clock(
setup: Setup<'_, '_, E, R>,
clock: K,
) -> Result<(Self, LineageHandle), SetupError<E, R>>
pub fn with_clock( setup: Setup<'_, '_, E, R>, clock: K, ) -> Result<(Self, LineageHandle), SetupError<E, R>>
Dioring::new, stamping failures with clock (DI-D-38): a test’s mock, for one, which
must keep StampClock’s promise that its readings never decrease.
§Errors
As Dioring::new.
Source§impl<B, E, C, R, K> Dioring<B, E, C, R, K>
impl<B, E, C, R, K> Dioring<B, E, C, R, K>
Sourcepub fn pump(&mut self, timeout: Option<Duration>) -> Result<bool>
pub fn pump(&mut self, timeout: Option<Duration>) -> Result<bool>
Drain what the ring has completed, on this thread (DI-D-55): drain it to empty and, if that
delivered entries, return; otherwise wait up to timeout – None is no limit, and
Duration::ZERO is a pump that does not wait – and drain again. Then make the provider’s
requests, and set the readiness event if entries became poppable. Whether they did. Pop what
became poppable with DurableRing::pop.
Only for an instance drained by its consumer, built with DeliveryMode::Pumped or
DeliveryMode::Signalled: a completion waits in the ring until a pump, so an instance that
is never pumped delivers nothing. A pumped instance waits on the ring’s own completion
event, and a signalled one on its completion_signal, which the
consumer may be waiting on too. It drains before it waits, so a wait of the consumer’s
own that took the signal cannot leave a pump blocked while completions sit in the ring. The
wait is made with the engine’s lock released, so another thread’s push, a provider’s answer or
a lineage handle’s release is not held up by it.
A return does not promise entries: the wait is satisfied by a raising whose completions an earlier drain took, and by the one signal the ring crate raises as it attaches the event (D-20), so a first pump may return at once. Pump in a loop, and pop to empty each time. With no limit and nothing in flight a pump never returns.
§Errors
io::ErrorKind::Unsupported for an instance built with DeliveryMode::Pool, which the
pool drains. Otherwise the wait’s own error, when the event cannot be waited on; the drain is
made all the same, so what has completed is delivered, and the entries it made poppable are
there to pop.
Sourcepub fn completion_signal(&self) -> Result<Event>
pub fn completion_signal(&self) -> Result<Event>
A duplicate of the event the thread pool sets whenever completions may be waiting, for the
consumer to wait on beside its own handles, and then to pump (DI-7.5). Each
call makes another duplicate of the one event.
The event is the instance’s own and shares nothing with the ring: it is auto-reset, so a wait takes the signal, and the consumer may set or reset it, which costs it nothing but its own wakeup, since a pump drains before it waits. It is set once as the instance is built, so a first wait may return with nothing to drain.
§Errors
io::ErrorKind::Unsupported unless the instance was built with DeliveryMode::Signalled.
Otherwise the duplication’s: the process cannot get another handle.
Sourcepub fn completion_event(&self) -> Result<OwnedHandle>
pub fn completion_event(&self) -> Result<OwnedHandle>
A handle to the ring’s own completion event, for the consumer to wait on beside its own
handles, and then to pump, with no thread-pool callback in between
(DI-D-55). Each call makes another
duplicate of the one event.
The handle carries SYNCHRONIZE access alone, so it can wait and nothing else: the kernel
refuses a set or a reset of the ring’s event through it. A holder that duplicates it asking
for more access can still get it, which Windows allows, so this guards against a handle used
for what it was not handed out for and is not a boundary within the process.
It is the ring’s event, not a copy of it. The event is auto-reset, so a wait through this
handle takes the signal, and the pump’s own wait does not see it; the pump drains before it
waits, so a consumer that waits here and then pumps on the same thread loses nothing. A
second thread blocked in pump with no limit while another waits here can be
left waiting for a signal the other took, so wait and pump from one thread. The ring signals
the event once as it is attached, so a first wait may return with nothing to drain.
§Errors
io::ErrorKind::Unsupported unless the instance was built with DeliveryMode::Pumped:
the other modes give the event to a wake of their own, which a wait of the consumer’s would
take wakes from (completion_signal is the event a signalled
instance offers). Otherwise the duplication’s: the process cannot get another handle.
Trait Implementations§
Source§impl<B: IoBuf, E: EpochId + 'static, C, R: IoBufMut, K: StampClock> Drop for Dioring<B, E, C, R, K>
impl<B: IoBuf, E: EpochId + 'static, C, R: IoBufMut, K: StampClock> Drop for Dioring<B, E, C, R, K>
Source§impl<B, E, C, R, K> DurableRing for Dioring<B, E, C, R, K>
impl<B, E, C, R, K> DurableRing for Dioring<B, E, C, R, K>
Source§type Ids = DioringIds<E, TimePoint<InterruptTime>>
type Ids = DioringIds<E, TimePoint<InterruptTime>>
Source§type Readiness = Event
type Readiness = Event
Event: an event
rather than a bare handle, so a front end can give it to a thread-pool wait without unsafe,
since an Event is guaranteed to be an event, never a mutex.Source§type Target = Win32FileTarget
type Target = Win32FileTarget
IoTarget. The Windows driver’s is
a Win32FileTarget.Source§fn readiness(&mut self) -> Result<Event>
fn readiness(&mut self) -> Result<Event>
pop has a failure to report (DI-D-58). One waiter; pop until None after
every wake; a wake with nothing to pop is normal. Read moreSource§fn add_target(
&mut self,
key: IoTargetKey,
target: Win32FileTarget,
) -> Result<(), AddTargetError<Win32FileTarget>>
fn add_target( &mut self, key: IoTargetKey, target: Win32FileTarget, ) -> Result<(), AddTargetError<Win32FileTarget>>
Source§fn remove_target(
&mut self,
key: IoTargetKey,
) -> Result<Win32FileTarget, RemoveTargetError<Self::Ids>>
fn remove_target( &mut self, key: IoTargetKey, ) -> Result<Win32FileTarget, RemoveTargetError<Self::Ids>>
Win32FileTarget it was given; one given at construction stays open until
the instance ends all the same, because the ring’s registration holds its file. Read moreSource§fn write_with(
&mut self,
file: IoTargetKey,
offset: u64,
buffer: B,
tag: Tag<'_, Self::Ids>,
context: C,
options: WriteOptions<Self::Ids>,
) -> PushResult<Self>where
B: IoBuf,
fn write_with(
&mut self,
file: IoTargetKey,
offset: u64,
buffer: B,
tag: Tag<'_, Self::Ids>,
context: C,
options: WriteOptions<Self::Ids>,
) -> PushResult<Self>where
B: IoBuf,
buffer to file at offset, tagged with tag’s epoch. The buffer and the context
come back on the operation’s completion. With a gate in options, the write is held until
the gate is durable (guarantee 9), and ends as NeverIssued if the gate or its own epoch is
abandoned first. Read moreSource§fn read_with(
&mut self,
file: IoTargetKey,
offset: u64,
buffer: B,
context: C,
options: ReadOptions<Self::Ids>,
) -> PushResult<Self>where
B: IoBufMut,
fn read_with(
&mut self,
file: IoTargetKey,
offset: u64,
buffer: B,
context: C,
options: ReadOptions<Self::Ids>,
) -> PushResult<Self>where
B: IoBufMut,
file at offset into buffer. Reads take no part in durability. The buffer,
filled, and the context come back on the operation’s completion. With a gate in options,
the read is held until the gate is durable, and ends as NeverIssued if it is abandoned
first. Read moreSource§fn make_durable_through(
&mut self,
through: Tag<'_, Self::Ids>,
) -> Result<DurabilityRequest<Self::Ids>, SealError<Self::Ids>>
fn make_durable_through( &mut self, through: Tag<'_, Self::Ids>, ) -> Result<DurabilityRequest<Self::Ids>, SealError<Self::Ids>>
through’s lineage at or below its epoch, and ask for them to be made
durable (DI-D-9). A new seal is answered on the queue (guarantee 4): by Failed if one of
its own flushes fails, by Blocked if they succeed but an unresolved failure holds an
epoch at or below it, and in every case by Durable { through } once the high-water mark
reaches it. A request at or below the seal point is a no-op answered here with the epoch’s
state (guarantee 7). A seal waits for the held gated writes it covers, as for writes in
flight. Read moreSource§fn durable_through(
&self,
lineage: Lineage,
) -> Result<Option<E>, UnknownLineage<Self::Ids>>
fn durable_through( &self, lineage: Lineage, ) -> Result<Option<E>, UnknownLineage<Self::Ids>>
None until something is. Read moreSource§fn sealed_through(
&self,
lineage: Lineage,
) -> Result<Option<E>, UnknownLineage<Self::Ids>>
fn sealed_through( &self, lineage: Lineage, ) -> Result<Option<E>, UnknownLineage<Self::Ids>>
None until something is sealed. Read moreSource§fn epoch_state(
&self,
epoch: Epoch<Self::Ids>,
) -> Result<EpochState<Self::Ids>, UnknownLineage<Self::Ids>>
fn epoch_state( &self, epoch: Epoch<Self::Ids>, ) -> Result<EpochState<Self::Ids>, UnknownLineage<Self::Ids>>
Source§fn default_lineage(&self) -> LineageHandle
fn default_lineage(&self) -> LineageHandle
Source§fn mint_lineage(&mut self, description: Option<String>) -> LineageHandle
fn mint_lineage(&mut self, description: Option<String>) -> LineageHandle
Source§fn end_lineage(
&mut self,
handle: LineageHandle,
) -> Result<(), EndLineageError<Self::Ids>>
fn end_lineage( &mut self, handle: LineageHandle, ) -> Result<(), EndLineageError<Self::Ids>>
LineageEnded entry, and the lineage is retired once its
operations in flight have completed. Releasing the last handle does the same. Read moreSource§fn retire_lineage(
&mut self,
handle: LineageHandle,
) -> Result<(), RetireLineageError<Self::Ids>>
fn retire_lineage( &mut self, handle: LineageHandle, ) -> Result<(), RetireLineageError<Self::Ids>>
Source§fn resolve(
&mut self,
items: Vec<(FailureToken, Resolution)>,
) -> Result<(), ResolveError<Self::Ids>>
fn resolve( &mut self, items: Vec<(FailureToken, Resolution)>, ) -> Result<(), ResolveError<Self::Ids>>
Heal, effective in each lineage the
failure holds when that lineage’s first seal made after this call that reaches the highest
epoch the lineage had been pushed by then finishes successfully (DI-D-41, DI-D-46), or
Abandon, effective at once (DI-D-12 (c)). The
call is validated whole and applied at one point in observation order. Read moreSource§fn import_failure(
&mut self,
scope: ImportScope<Self::Ids>,
) -> Result<Imported<Self::Ids>, UnknownLineage<Self::Ids>>
fn import_failure( &mut self, scope: ImportScope<Self::Ids>, ) -> Result<Imported<Self::Ids>, UnknownLineage<Self::Ids>>
scope, and its token arrives with its Failed entry.
The answer names the failure, and any domain the scope named that the instance has never
been given (DI-D-46). Read moreSource§fn failures(&self) -> Vec<FailureInfo<Self::Ids>>
fn failures(&self) -> Vec<FailureInfo<Self::Ids>>
Source§fn take_token(&mut self, failure: FailureId) -> Option<FailureToken>
fn take_token(&mut self, failure: FailureId) -> Option<FailureToken>
None otherwise, including for a failure that is resolved, another instance’s, or healed
and waiting for its seal.Source§fn close(self) -> Leftovers<Self::Ids, B, C>
fn close(self) -> Leftovers<Self::Ids, B, C>
Source§impl<B, E, C, R, K> RegisteredBufferRing for Dioring<B, E, C, R, K>
impl<B, E, C, R, K> RegisteredBufferRing for Dioring<B, E, C, R, K>
Source§type Registered = R
type Registered = R
Source§fn with_registered_buffer<T>(
&mut self,
i: u32,
f: impl FnOnce(&[u8]) -> T,
) -> Result<T>
fn with_registered_buffer<T>( &mut self, i: u32, f: impl FnOnce(&[u8]) -> T, ) -> Result<T>
f on the bytes of registered buffer i, and return what it returns. The instance
holds the registration (DI-D-17) and lends the bytes for the call alone, under its own lock:
an implementation whose registration is shared with its delivery can lend them no longer.
While f runs, that lock is held, and nothing the lock guards – completions included –
makes progress. Read moreSource§fn with_registered_buffer_mut<T>(
&mut self,
i: u32,
f: impl FnOnce(&mut [u8]) -> T,
) -> Result<T>
fn with_registered_buffer_mut<T>( &mut self, i: u32, f: impl FnOnce(&mut [u8]) -> T, ) -> Result<T>
with_registered_buffer, with the bytes lent mutably. Read moreSource§fn write_registered_with(
&mut self,
file: IoTargetKey,
offset: u64,
span: RegisteredSpan,
tag: Tag<'_, Self::Ids>,
context: C,
options: WriteOptions<Self::Ids>,
) -> PushResult<Self>
fn write_registered_with( &mut self, file: IoTargetKey, offset: u64, span: RegisteredSpan, tag: Tag<'_, Self::Ids>, context: C, options: WriteOptions<Self::Ids>, ) -> PushResult<Self>
span of the registered buffers to file at offset, tagged with tag’s epoch. Its
completion carries no buffer: the bytes belong to the registration. Read moreSource§fn read_registered_with(
&mut self,
file: IoTargetKey,
offset: u64,
span: RegisteredSpan,
context: C,
options: ReadOptions<Self::Ids>,
) -> PushResult<Self>
fn read_registered_with( &mut self, file: IoTargetKey, offset: u64, span: RegisteredSpan, context: C, options: ReadOptions<Self::Ids>, ) -> PushResult<Self>
Source§fn write_registered(
&mut self,
file: IoTargetKey,
offset: u64,
span: RegisteredSpan,
tag: Tag<'_, Self::Ids>,
context: Self::Context,
) -> Result<<Self::Ids as Identities>::OpId, PushError<Self::Ids, Self::Buffer, Self::Context>>
fn write_registered( &mut self, file: IoTargetKey, offset: u64, span: RegisteredSpan, tag: Tag<'_, Self::Ids>, context: Self::Context, ) -> Result<<Self::Ids as Identities>::OpId, PushError<Self::Ids, Self::Buffer, Self::Context>>
write_registered_with with default options. Read moreSource§fn read_registered(
&mut self,
file: IoTargetKey,
offset: u64,
span: RegisteredSpan,
context: Self::Context,
) -> Result<<Self::Ids as Identities>::OpId, PushError<Self::Ids, Self::Buffer, Self::Context>>
fn read_registered( &mut self, file: IoTargetKey, offset: u64, span: RegisteredSpan, context: Self::Context, ) -> Result<<Self::Ids as Identities>::OpId, PushError<Self::Ids, Self::Buffer, Self::Context>>
read_registered_with with default options. Read more