pub struct PushOptions { /* private fields */ }Expand description
Per-push options shared across every op builder (M3.2).
Implementations§
Source§impl PushOptions
impl PushOptions
Sourcepub fn drain_preceding(self, drain: bool) -> Self
pub fn drain_preceding(self, drain: bool) -> Self
Set IOSQE_FLAGS_DRAIN_PRECEDING_OPS: this op does not complete until
every op already queued on this batch’s ring has completed. A
barrier, not a cheap tag – but a one-sided one, and the direction
it does not cover is the surprising half.
Stated in terms of completion rather than of when the op starts, throughout: user mode cannot see execution begin, only completions posted, so completion order is both what was measured and the only thing a caller can act on (D-47).
§Ring-wide in reach, one-sided in effect
Measured, not inferred (D-24 and D-47 in DESIGN-NOTES.md). The wait
reaches every operation outstanding on the ring, not only the ones
queued in this batch, and results were identical whether the sequence
went in one Batch::submit or three.
It does not hold back operations pushed after it. Those can complete while this one is still outstanding – observed across about 4,500 trials, and in the worst case every one of 32 subsequent writes completed first. An earlier version of this documentation said they were held; that was measured over too few runs to see a fault this rare, and it was wrong.
The consequence to plan for: this delays the flagged op, not the ring. Later work is not blocked, so it cannot be used to fence anything that follows. A consumer that needs later work to begin only after this op is durable must sequence that itself, by waiting for its completion before submitting.
§The barrier stops at the ring’s edge
It orders SQEs against SQEs, and nothing else. Any non-ring I/O – an
overlapped DeviceIoControl, anything issued through
windows-overlapped-io-sys, a plain blocking write – is outside it in
both directions: this flag can neither make a ring op wait for a
non-ring op nor make a non-ring op wait for ring ops.
A consumer mixing both paths is the normal case rather than an exotic
one, and it must enforce that ordering in its own code. What this
crate offers toward it is IoRing::completion_event, which makes
waiting on the ring alongside other handles expressible without
giving up the ring or blocking a thread in a drain.
§Ordering, never durability by itself
This flag orders operations; it does not flush anything. It is,
however, what makes a flush cover the writes before it: a flush pushed
after a batch of writes without this flag routinely completes while
many of those writes are still outstanding (D-23 in DESIGN-NOTES.md,
measured at 17 and 23 of 32 writes finishing after the flush did). So
the obvious spelling – push the writes, then push a flush – silently
does not make those writes durable.
A flush does not take its barrier decision from here, for exactly that
reason: Batch::flush_owned requires a FlushCoverage instead, so the
choice cannot be inherited from a default (M12.1, D-25).