pub struct LocalLevelCell { /* private fields */ }Expand description
locallevel storage: shared for parameter scoping, per-thread for
diagnostics.
!!! WARNING: RUST-ONLY !!! C has one int locallevel
(Src/params.c:54) serving both jobs, because with one thread they are
the same number.
zshrs cannot simply make it per-thread. locallevel is the level a
parameter is STAMPED with (Src/params.c:5837 locallevel++ in
startparamscope) and the level scanendscope compares every entry
against on scope exit (Src/params.c:5904-5907, if (pm->level > locallevel)) — and the param table those stamps live in is one shared
table that async_precmd hooks deliberately write into. Give each
thread its own counter and two threads both stamp level 1 in the same
table, so one thread’s endparamscope deletes the other’s locals: a
strictly worse version of the $BUFFER loss quiesce was added for.
So load — every parameter-scoping reader — keeps
returning the shared value, unchanged.
What a worker must NOT contaminate is the other job: the
“am I inside a function” test the error formatters make
(Src/utils.c:150 if (unset(SHINSTDIN) || locallevel), :301 in
zerrmsg). A hook running on a worker raised the shared counter, and
an error the user caused at top level came out formatted as if it had
happened inside a function — with a line number and a function-name
prefix zsh does not print. here answers that question
for the CALLING thread, and the formatters read it.
Every mutation goes through this type, so the per-thread depth cannot
drift away from the sites that move the shared counter: the four
methods below are the entire mutation surface of params::locallevel.
Implementations§
Source§impl LocalLevelCell
impl LocalLevelCell
Sourcepub fn load(&self, order: Ordering) -> i32
pub fn load(&self, order: Ordering) -> i32
Mirrors AtomicI32::load — the SHARED counter, for param scoping.
Sourcepub fn store(&self, val: i32, order: Ordering)
pub fn store(&self, val: i32, order: Ordering)
Mirrors AtomicI32::store. Sites that save and restore the whole
counter (computil’s comparguments bracket, param_private’s
hoist) mean “this thread is now at level v”, so the thread’s own
depth follows.
Sourcepub fn fetch_add(&self, val: i32, order: Ordering) -> i32
pub fn fetch_add(&self, val: i32, order: Ordering) -> i32
Mirrors AtomicI32::fetch_add, returning the previous SHARED value.
Sourcepub fn fetch_sub(&self, val: i32, order: Ordering) -> i32
pub fn fetch_sub(&self, val: i32, order: Ordering) -> i32
Mirrors AtomicI32::fetch_sub, returning the previous SHARED value.
Sourcepub fn here(&self) -> i32
pub fn here(&self) -> i32
The calling thread’s OWN function-scope depth — what C’s
locallevel would read if this thread were the only one, which is
what the error formatters need. Clamped at zero: a thread whose
first act is endparamscope (a scope opened before it existed)
would otherwise report a negative depth.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for LocalLevelCell
impl RefUnwindSafe for LocalLevelCell
impl Send for LocalLevelCell
impl Sync for LocalLevelCell
impl Unpin for LocalLevelCell
impl UnsafeUnpin for LocalLevelCell
impl UnwindSafe for LocalLevelCell
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
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
Source§impl<F, W, T, D> Deserialize<With<T, W>, D> for F
impl<F, W, T, D> Deserialize<With<T, W>, D> for F
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> 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