simplify code that locks log buffer for reading

This commit is contained in:
Chris Beck
2025-12-05 20:27:55 -07:00
parent 3c88ba80a5
commit 74baa63f50
3 changed files with 19 additions and 16 deletions
+2 -1
View File
@@ -39,6 +39,7 @@ impl<T> CircularBuffer<T> {
} }
/// Returns the number of elements in the buffer. /// Returns the number of elements in the buffer.
#[allow(unused)]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.buf.len() self.buf.len()
} }
@@ -56,7 +57,7 @@ impl<T> CircularBuffer<T> {
} }
/// Returns an iterator over the elements, from oldest to newest. /// Returns an iterator over the elements, from oldest to newest.
pub fn iter(&self) -> impl DoubleEndedIterator<Item = &T> { pub fn iter(&self) -> impl DoubleEndedIterator<Item = &T> + ExactSizeIterator {
self.buf.iter() self.buf.iter()
} }
+12 -11
View File
@@ -41,18 +41,19 @@ impl LogBuffer {
buf.clear(); buf.clear();
} }
/// Iterate over all messages without modifying the buffer. /// Access the buffer contents via an iterator.
/// ///
/// Messages are passed to `f` in reverse order (newest first). /// The iterator yields messages in reverse order (newest first) and
pub fn for_each(&self, mut f: impl FnMut(&LogMessage)) { /// implements `ExactSizeIterator`, so `iter.len()` returns the count.
// NOTE: We use `&mut dyn ExactSizeIterator` rather than `impl FnOnce(impl ExactSizeIterator)`
// because Rust doesn't allow nested `impl Trait` in that position. A generic parameter
// `F: FnOnce(I) where I: ExactSizeIterator` doesn't work either because `I` would be
// caller-determined, but we need to pass our concrete iterator type. HRTB with the
// concrete type (`F: for<'a> FnOnce(Rev<vec_deque::Iter<'a, T>>)`) works but leaks
// implementation details.
pub fn with_iter<R>(&self, f: impl FnOnce(&mut dyn ExactSizeIterator<Item = &LogMessage>) -> R) -> R {
let buf = self.buf.lock().unwrap(); let buf = self.buf.lock().unwrap();
for log_msg in buf.iter().rev() { let mut iter = buf.iter().rev();
f(log_msg); f(&mut iter)
}
}
/// Returns the number of messages currently in the buffer.
pub fn len(&self) -> usize {
self.buf.lock().unwrap().len()
} }
} }
+4 -3
View File
@@ -129,10 +129,11 @@ impl LogHandler {
use std::fmt::Write; use std::fmt::Write;
writeln!(&mut text, "=== [{origin}] ===").unwrap(); writeln!(&mut text, "=== [{origin}] ===").unwrap();
writeln!(&mut text, "{} log messages (newest first):", buffer.len()).unwrap(); buffer.with_iter(|iter| {
writeln!(&mut text, "{} log messages (newest first):", iter.len()).unwrap();
buffer.for_each(|log_msg| { for log_msg in iter {
self.write_log_msg(&mut text, log_msg, now); self.write_log_msg(&mut text, log_msg, now);
}
}); });
text.push('\n'); text.push('\n');
} }