pub struct Held {
conversation: Mutex<Conversation>,
folded: Condvar,
}Expand description
One seat’s conversation, and the fold that may be running over it.
Two locks, because a fold must not be held against the stream and a reader must not see half of one. A fold takes the messages out in O(1) under the mutex, renders them outside it - so the socket’s single stream folder never waits on a render - and puts them back under the mutex with the spans. Between those two the seat holds no messages and the PREVIOUS fold’s boundaries, and a page sliced on those walks off the end of an empty list.
So the mutex is paired with a condvar: a reader waits out a fold in progress rather than looking at it. The wait is on the reader’s own blocking task, and it is bounded by one render.
Fields§
§conversation: Mutex<Conversation>§folded: CondvarImplementations§
Source§impl Held
impl Held
pub fn new(conversation: Conversation) -> Self
Sourcepub fn holds_occupant(&self, occupant: Option<&SessionId>) -> bool
pub fn holds_occupant(&self, occupant: Option<&SessionId>) -> bool
Whether this copy belongs to the seat’s current occupant.
A copy with no occupant matches anything, and so does a header naming nobody: a transcript that named no session seeds a copy with no occupant, and a sleeping seat’s header names no run - neither is discarded for lacking a fact nothing ever recorded.
Sourcepub fn lock(&self) -> MutexGuard<'_, Conversation>
pub fn lock(&self) -> MutexGuard<'_, Conversation>
The conversation, waiting out a fold that is running over it.
Sourcefn install(&self, window: Window, rendered: Rendered, complete: bool)
fn install(&self, window: Window, rendered: Rendered, complete: bool)
Put a fold’s result back and wake every reader waiting on it.
Sourcepub fn read<T>(&self, read: impl FnOnce(&Conversation) -> T) -> T
pub fn read<T>(&self, read: impl FnOnce(&Conversation) -> T) -> T
Fold if needed, then read, retrying once if a reseed landed in between.
Two acquisitions, and the gap between them is why this retries. A
Connected or a /resume can replace the conversation
between the fold and the read, and what a reader then holds is the new
messages against boundaries the fold cleared - one turn covering the
whole conversation rather than a window of them. The retry closes the
common case; a second reseed inside the second window still gets
through, which is stated in the PR rather than claimed away.
Auto Trait Implementations§
impl !Freeze for Held
impl RefUnwindSafe for Held
impl Send for Held
impl Sync for Held
impl Unpin for Held
impl UnsafeUnpin for Held
impl UnwindSafe for Held
Blanket Implementations§
§impl<T> AnySync for T
impl<T> AnySync for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more