Skip to main content

Dioring

Struct Dioring 

Source
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>
where B: IoBuf + Send + 'static, E: EpochId + Send + Sync + 'static, C: Send + 'static, R: IoBufMut + Send + 'static,

Source

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>
where B: IoBuf + Send + 'static, E: EpochId + Send + Sync + 'static, C: Send + 'static, R: IoBufMut + Send + 'static, K: TimeBase,

Source

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>
where B: IoBuf + Send + 'static, E: EpochId + Send + Sync + 'static, C: Send + 'static, R: IoBufMut + Send + 'static, K: TimeBase,

Source

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.

Source

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.

Source

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>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl<B, E, C, R, K> DurableRing for Dioring<B, E, C, R, K>
where B: IoBuf + Send + 'static, E: EpochId + Send + Sync + 'static, C: Send + 'static, R: IoBufMut + Send + 'static, K: TimeBase,

Source§

type Ids = DioringIds<E, TimePoint<InterruptTime>>

The implementation’s identity types, and the consumer’s epoch-id type.
Source§

type Buffer = B

The owned buffer type of writes and reads.
Source§

type Context = C

The consumer’s per-operation context, handed back with each completion.
Source§

type Readiness = Event

The implementation’s readiness signal (DI-D-28, DI-D-52 Q6): what a consumer waits on, in whatever form the platform waits. The Windows driver’s is an auto-reset 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

The implementation’s targets (DI-D-48, DI-D-50): what a write or a read addresses and a commit makes durable, each stating what it is through IoTarget. The Windows driver’s is a Win32FileTarget.
Source§

fn readiness(&mut self) -> Result<Event>

A duplicate of the readiness signal (DI-D-28): one the instance owns, set after an entry becomes poppable and at least whenever the queue goes from empty to non-empty, and when a 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 more
Source§

fn add_target( &mut self, key: IoTargetKey, target: Win32FileTarget, ) -> Result<(), AddTargetError<Win32FileTarget>>

Give the instance a target after construction, under a key unique within the instance. What the target states – its flush domains among it – is read once, now (DI-2.10 point 3): to change it, remove the target and add it again. Read more
Source§

fn remove_target( &mut self, key: IoTargetKey, ) -> Result<Win32FileTarget, RemoveTargetError<Self::Ids>>

Take a target back, under the key it was given with. Its key may be reused at once. dioring hands back the 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 more
Source§

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,

Write 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 more
Source§

fn read_with( &mut self, file: IoTargetKey, offset: u64, buffer: B, context: C, options: ReadOptions<Self::Ids>, ) -> PushResult<Self>
where B: IoBufMut,

Read from 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 more
Source§

fn pop(&mut self) -> Result<Option<EntryOf<Self>>>

The next entry, or None when the queue is empty. Never waits; wait on readiness. Read more
Source§

fn make_durable_through( &mut self, through: Tag<'_, Self::Ids>, ) -> Result<DurabilityRequest<Self::Ids>, SealError<Self::Ids>>

Seal every epoch of 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 more
Source§

fn durable_through( &self, lineage: Lineage, ) -> Result<Option<E>, UnknownLineage<Self::Ids>>

The lineage’s high-water mark: the highest epoch id through which every epoch is durable, or None until something is. Read more
Source§

fn sealed_through( &self, lineage: Lineage, ) -> Result<Option<E>, UnknownLineage<Self::Ids>>

The lineage’s seal point, or None until something is sealed. Read more
Source§

fn epoch_state( &self, epoch: Epoch<Self::Ids>, ) -> Result<EpochState<Self::Ids>, UnknownLineage<Self::Ids>>

An epoch’s state. Read more
Source§

fn default_lineage(&self) -> LineageHandle

A handle to the lineage that always exists: a copy of the one construction returned. The instance holds a copy of its own, so the default lineage never ends while it lives.
Source§

fn mint_lineage(&mut self, description: Option<String>) -> LineageHandle

A new lineage, with an optional description for the consumer’s own reports (DI-D-19). Releasing the last copy of its handle ends it (DI-D-40).
Source§

fn lineages(&self) -> Vec<LineageInfo<Self::Ids>>

Every live lineage, the default among them.
Source§

fn end_lineage( &mut self, handle: LineageHandle, ) -> Result<(), EndLineageError<Self::Ids>>

End a lineage through its last handle (DI-D-30): every epoch of it not yet durable is abandoned, reported by a LineageEnded entry, and the lineage is retired once its operations in flight have completed. Releasing the last handle does the same. Read more
Source§

fn retire_lineage( &mut self, handle: LineageHandle, ) -> Result<(), RetireLineageError<Self::Ids>>

Retire a lineage through its last handle, abandoning nothing: refused unless nothing of it is in flight, uncovered, or held by an unresolved failure. Read more
Source§

fn resolve( &mut self, items: Vec<(FailureToken, Resolution)>, ) -> Result<(), ResolveError<Self::Ids>>

Resolve one or more failures, each by its token: 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 more
Source§

fn import_failure( &mut self, scope: ImportScope<Self::Ids>, ) -> Result<Imported<Self::Ids>, UnknownLineage<Self::Ids>>

Record a failure learned of outside the instance (DI-D-12 (h)). Its suspect set is built by the same rule as any other’s, within 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 more
Source§

fn failures(&self) -> Vec<FailureInfo<Self::Ids>>

The unresolved failures, in the order they were observed.
Source§

fn take_token(&mut self, failure: FailureId) -> Option<FailureToken>

A token for an unresolved failure whose token is not live – it was closed or dropped. 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>

End the instance and hand back what is left (DI-D-25): the gated operations the kernel never saw, with their buffers and contexts, in push order; the unresolved failures; and every lineage with its final high-water mark. Seals and flushes nothing. Returns once every kernel operation and every durability-provider call in flight has completed, as drop does; entries not yet popped are discarded, and nothing already reported is undone.
Source§

fn write( &mut self, file: IoTargetKey, offset: u64, buffer: Self::Buffer, tag: Tag<'_, Self::Ids>, context: Self::Context, ) -> Result<<Self::Ids as Identities>::OpId, PushError<Self::Ids, Self::Buffer, Self::Context>>
where Self::Buffer: IoBuf,

write_with with default options: cached. Read more
Source§

fn read( &mut self, file: IoTargetKey, offset: u64, buffer: Self::Buffer, context: Self::Context, ) -> Result<<Self::Ids as Identities>::OpId, PushError<Self::Ids, Self::Buffer, Self::Context>>
where Self::Buffer: IoBufMut,

read_with with default options. Read more
Source§

impl<B, E, C, R, K> RegisteredBufferRing for Dioring<B, E, C, R, K>
where B: IoBuf + Send + 'static, E: EpochId + Send + Sync + 'static, C: Send + 'static, R: IoBufMut + Send + 'static, K: TimeBase,

Source§

type Registered = R

The registered-buffer type.
Source§

fn with_registered_buffer<T>( &mut self, i: u32, f: impl FnOnce(&[u8]) -> T, ) -> Result<T>

Run 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 more
Source§

fn with_registered_buffer_mut<T>( &mut self, i: u32, f: impl FnOnce(&mut [u8]) -> T, ) -> Result<T>

As with_registered_buffer, with the bytes lent mutably. Read more
Source§

fn write_registered_with( &mut self, file: IoTargetKey, offset: u64, span: RegisteredSpan, tag: Tag<'_, Self::Ids>, context: C, options: WriteOptions<Self::Ids>, ) -> PushResult<Self>

Write 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 more
Source§

fn read_registered_with( &mut self, file: IoTargetKey, offset: u64, span: RegisteredSpan, context: C, options: ReadOptions<Self::Ids>, ) -> PushResult<Self>

Read from file at offset into span of the registered buffers. Read more
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>>

write_registered_with with default options. Read more
Source§

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

Auto Trait Implementations§

§

impl<B, E = u64, C = (), R = Vec<u8>, K = InterruptStamps> !RefUnwindSafe for Dioring<B, E, C, R, K>

§

impl<B, E = u64, C = (), R = Vec<u8>, K = InterruptStamps> !Sync for Dioring<B, E, C, R, K>

§

impl<B, E = u64, C = (), R = Vec<u8>, K = InterruptStamps> !UnwindSafe for Dioring<B, E, C, R, K>

§

impl<B, E, C, R, K> Freeze for Dioring<B, E, C, R, K>
where Option<Delivery<E, B, C, K, R>>: Freeze, Arc<Hub<E, B, C, K, R>>: Freeze, Option<Box<dyn DurabilityProvider<DioringIds<E, TimePoint<InterruptTime>>>>>: Freeze,

§

impl<B, E, C, R, K> Send for Dioring<B, E, C, R, K>
where Option<Delivery<E, B, C, K, R>>: Send, Arc<Hub<E, B, C, K, R>>: Send, Option<Box<dyn DurabilityProvider<DioringIds<E, TimePoint<InterruptTime>>>>>: Send,

§

impl<B, E, C, R, K> Unpin for Dioring<B, E, C, R, K>
where Option<Delivery<E, B, C, K, R>>: Unpin, Arc<Hub<E, B, C, K, R>>: Unpin, Option<Box<dyn DurabilityProvider<DioringIds<E, TimePoint<InterruptTime>>>>>: Unpin,

§

impl<B, E, C, R, K> UnsafeUnpin for Dioring<B, E, C, R, K>
where Option<Delivery<E, B, C, K, R>>: UnsafeUnpin, Arc<Hub<E, B, C, K, R>>: UnsafeUnpin, Option<Box<dyn DurabilityProvider<DioringIds<E, TimePoint<InterruptTime>>>>>: UnsafeUnpin,

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> 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, 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.