lattice_ui_tui/actor_call_counter.rs
1//! Per-thread counter for `App::read_editor` / `App::mutate_editor`
2//! / `App::mutate_editor_with` calls.
3//!
4//! Slice `3c.extension.fold-rs.test`: regression-test scaffolding
5//! that asserts the per-frame paint path doesn't reach the actor
6//! mailbox. The previous regression — `frame_120_lines/200` went
7//! from 90µs to 43.73ms because 120 per-line `read_editor` calls
8//! crept into `compose_visible_lines_inner` — would have been
9//! caught by a "this path makes 0 actor calls" assertion if one
10//! had existed.
11//!
12//! The counter is a `Cell<u64>` in thread-local storage; the
13//! seam methods `bump()` on entry. Tests call [`snapshot`] to
14//! read the current count, drive the path under test, then call
15//! [`snapshot`] again and assert the delta is bounded.
16//!
17//! Non-test builds: one inlined thread-local increment per seam
18//! call (~ns). Negligible against the ~µs–~100µs cost the seam
19//! itself pays.
20
21use std::cell::Cell;
22
23thread_local! {
24 static COUNT: Cell<u64> = const { Cell::new(0) };
25}
26
27/// Increment the per-thread call count. Called by the
28/// `App::{read,mutate,mutate_with}_editor` seam.
29#[inline]
30pub fn bump() {
31 COUNT.with(|c| c.set(c.get() + 1));
32}
33
34/// Read the current count. Tests use this to capture before/after
35/// snapshots around a code path under test.
36#[inline]
37pub fn snapshot() -> u64 {
38 COUNT.with(|c| c.get())
39}
40
41/// Reset the count to zero. Optional — tests can also just
42/// compute deltas via `snapshot()` before / after.
43#[inline]
44pub fn reset() {
45 COUNT.with(|c| c.set(0));
46}