pub trait LogSink: Send + Sync {
// Required methods
fn emit(&self, lvl: Level, msg: &str);
fn emit_error(&self, msg: &str);
}Expand description
Pluggable destination for diagnostic emissions. The default
StderrSink preserves the linesmith [<level>]: <msg> format
external scripts grep for; the TUI swaps in a CapturedSink
for the duration of the alt-screen so macro emissions land in
the warnings panel instead of corrupting the painted frame.
&self (not &mut self) so a sink instance can be shared via
Arc<dyn LogSink>. The Send + Sync bound is what Arc<dyn _>
requires and lets background plugin emitters share the slot
safely with the render thread. The active-sink slot is an
RwLock: emits take read locks (concurrent) and install_sink
takes the write lock, which waits for in-flight emits to drain
before swapping. This applies only to dispatches that go
through emit / emit_error — a thread that holds its own
Arc<dyn LogSink> (the prior returned by install_sink, or a
future plugin handle) can still drive that sink directly after
a swap.
Implementations must not call back into emit / emit_error
or the lsm_warn! / lsm_debug! / lsm_error! macros from
within their own emit / emit_error. The slot’s read lock is
held across the dispatch, and std::sync::RwLock’s reentrancy
is platform-defined — a recursive read can deadlock against a
pending install_sink on writer-preferring runtimes (musl,
Windows SRW). lsm-261p tracks evaluating a fair RwLock so this
invariant can relax.
Required Methods§
Sourcefn emit(&self, lvl: Level, msg: &str)
fn emit(&self, lvl: Level, msg: &str)
Emit a level-gated diagnostic. The caller has already
confirmed the level is enabled — the sink writes
unconditionally. Implementations defensively no-op on
Level::Off rather than relying on the caller; the macros
never pass Off, but emit() is pub.
Sourcefn emit_error(&self, msg: &str)
fn emit_error(&self, msg: &str)
Emit a structural-failure diagnostic. Always fires regardless
of the configured level — LINESMITH_LOG=off users still
see “the statusline broke” because there’s no other channel.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".