use std::{cell::Cell, panic::Location};
#[derive(Clone, Copy, PartialEq, Eq)]
pub(in crate::flash) struct Mode {
active: bool,
ambient: bool,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub(in crate::flash) enum Credit {
None,
Running,
Parked,
}
struct ThreadCtx {
credit: Cell<Credit>,
cur_async: Cell<Option<(u64, &'static Location<'static>)>>,
dedicated: Cell<bool>,
mode: Cell<Mode>,
poll_depth: Cell<u32>,
}
thread_local! {
static CTX: ThreadCtx = const {
ThreadCtx {
mode: Cell::new(Mode {
ambient: false,
active: false,
}),
credit: Cell::new(Credit::None),
poll_depth: Cell::new(0),
dedicated: Cell::new(false),
cur_async: Cell::new(None),
}
};
}
#[inline]
#[must_use]
pub(crate) fn flash_enabled() -> bool {
CTX.with(|c| c.mode.get().active)
}
#[inline]
#[must_use]
pub(crate) fn flash_ambient() -> bool {
CTX.with(|c| c.mode.get().ambient)
}
#[derive(Clone, Copy)]
pub(in crate::flash) struct ModeSnapshot {
prev: Mode,
set: Mode,
}
pub(in crate::flash) fn push_active(on: bool) -> ModeSnapshot {
CTX.with(|c| {
let prev = c.mode.get();
let set = Mode {
active: on && prev.ambient,
..prev
};
c.mode.set(set);
ModeSnapshot { prev, set }
})
}
pub(in crate::flash) fn push_ambient(on: bool) -> ModeSnapshot {
CTX.with(|c| {
let prev = c.mode.get();
let set = Mode {
ambient: on,
..prev
};
c.mode.set(set);
ModeSnapshot { prev, set }
})
}
pub(in crate::flash) fn restore_mode(snap: ModeSnapshot) {
CTX.with(|c| {
debug_assert!(
c.mode.get() == snap.set || std::thread::panicking(),
"BUG: non-LIFO mode-scope drop — mode is not the one this scope set (an \
interleaved later scope is still alive, or was already restored over this one)"
);
c.mode.set(snap.prev);
});
}
pub(in crate::flash) fn credit() -> Credit {
CTX.with(|c| c.credit.get())
}
pub(in crate::flash) fn set_credit(v: Credit) {
CTX.with(|c| c.credit.set(v));
}
pub(in crate::flash) fn poll_depth() -> u32 {
CTX.with(|c| c.poll_depth.get())
}
pub(in crate::flash) fn set_poll_depth(v: u32) {
CTX.with(|c| c.poll_depth.set(v));
}
pub(in crate::flash) fn dedicated() -> bool {
CTX.with(|c| c.dedicated.get())
}
pub(in crate::flash) fn set_dedicated(v: bool) {
CTX.with(|c| c.dedicated.set(v));
}
pub(in crate::flash) fn cur_async() -> Option<(u64, &'static Location<'static>)> {
CTX.with(|c| c.cur_async.get())
}
pub(in crate::flash) fn swap_cur_async(
v: Option<(u64, &'static Location<'static>)>,
) -> Option<(u64, &'static Location<'static>)> {
CTX.with(|c| c.cur_async.replace(v))
}