Files
Kigi-CLI/crates/common/kigi-interjection-core/src/events.rs
T
ZacharyZhang-NY a02b555e66 docs(comments): rewrite comments across all crates to the guidelines
Sweep every first-party crate source (1956 .rs files) to the project comment
guidelines: delete redundant restatements, decorative banners, change
narration, and end-of-line comments; keep and tighten the crucial ones
(invariants, bug rationale, SAFETY blocks, ported-source attribution).

No functional code changed. Every edit is proven comment-only against the
prior tree by a comment-stripping lexer (string/char/raw-string aware) plus a
separate doctest-fence check. Where removing a comment made rustfmt or clippy
want to re-lay-out adjacent code, the minimal triggering comment is restored so
code tokens stay byte-identical.

Gates green: cargo fmt --all --check (0 diffs), cargo check and cargo clippy
--workspace --all-targets (0 warnings).

Adds scripts/check_codegen_comment_guidelines.py — the enforcement gate for
these guidelines (flags banners, end-of-line comments, change narration, and
commented-out code).
2026-07-23 16:55:39 -04:00

174 lines
4.2 KiB
Rust

//! Shared push-path event queue: producers enqueue; readers drain at hook
//! points. Internally synchronized and `Arc`-shared (clones share one queue),
//! matching [`crate::buffer::InterjectionBuffer`].
use std::sync::{Arc, Mutex, MutexGuard};
#[derive(Debug)]
pub struct EventQueue<E> {
events: Arc<Mutex<Vec<E>>>,
}
impl<E> Clone for EventQueue<E> {
fn clone(&self) -> Self {
Self {
events: Arc::clone(&self.events),
}
}
}
impl<E> Default for EventQueue<E> {
fn default() -> Self {
Self::new()
}
}
impl<E> EventQueue<E> {
pub fn new() -> Self {
Self {
events: Arc::new(Mutex::new(Vec::new())),
}
}
pub fn push(&self, event: E) {
self.lock().push(event);
}
/// Push, then drop oldest entries so length stays ≤ `max`.
pub fn push_capped(&self, event: E, max: usize) {
let mut q = self.lock();
q.push(event);
if q.len() > max {
let excess = q.len() - max;
q.drain(..excess);
}
}
pub fn len(&self) -> usize {
self.lock().len()
}
pub fn is_empty(&self) -> bool {
self.lock().is_empty()
}
/// Remove matching events; keep the rest. Both sets stay FIFO.
pub fn drain_matching(&self, take: impl Fn(&E) -> bool) -> Vec<E> {
let mut q = self.lock();
let (matched, kept): (Vec<E>, Vec<E>) =
std::mem::take(&mut *q).into_iter().partition(|e| take(e));
*q = kept;
matched
}
pub fn drain_all(&self) -> Vec<E> {
std::mem::take(&mut *self.lock())
}
pub fn clear(&self) {
self.lock().clear();
}
fn lock(&self) -> MutexGuard<'_, Vec<E>> {
self.events.lock().unwrap_or_else(|e| e.into_inner())
}
}
impl<E: Clone> EventQueue<E> {
/// Snapshot without draining.
pub fn snapshot(&self) -> Vec<E> {
self.lock().clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn push_and_len() {
let q: EventQueue<u32> = EventQueue::new();
assert!(q.is_empty());
q.push(1);
q.push(2);
assert_eq!(q.len(), 2);
}
#[test]
fn clones_share_one_queue() {
let q: EventQueue<u32> = EventQueue::new();
let q2 = q.clone();
q.push(7);
assert_eq!(q2.len(), 1);
}
#[test]
fn push_capped_drops_oldest() {
let q: EventQueue<u32> = EventQueue::new();
for i in 0..5 {
q.push_capped(i, 3);
}
assert_eq!(q.drain_matching(|_| true), vec![2, 3, 4]);
assert!(q.is_empty());
}
#[test]
fn drain_matching_returns_matched_retains_rest_fifo() {
let q: EventQueue<u32> = EventQueue::new();
for i in 0..6 {
q.push(i);
}
let evens = q.drain_matching(|n| n % 2 == 0);
assert_eq!(evens, vec![0, 2, 4]);
assert_eq!(q.drain_matching(|_| true), vec![1, 3, 5]);
}
#[test]
fn push_capped_under_limit_keeps_all() {
let q: EventQueue<u32> = EventQueue::new();
q.push_capped(1, 5);
q.push_capped(2, 5);
assert_eq!(q.drain_matching(|_| true), vec![1, 2]);
}
#[test]
fn drain_matching_none_match_retains_all() {
let q: EventQueue<u32> = EventQueue::new();
q.push(1);
q.push(2);
assert!(q.drain_matching(|n| *n > 10).is_empty());
assert_eq!(q.len(), 2);
}
#[test]
fn drain_matching_on_empty_is_empty() {
let q: EventQueue<u32> = EventQueue::new();
assert!(q.drain_matching(|_| true).is_empty());
}
#[test]
fn drain_all_empties_in_fifo_order() {
let q: EventQueue<u32> = EventQueue::new();
q.push(1);
q.push(2);
assert_eq!(q.drain_all(), vec![1, 2]);
assert!(q.is_empty());
}
#[test]
fn clear_discards_all() {
let q: EventQueue<u32> = EventQueue::new();
q.push(1);
q.clear();
assert!(q.is_empty());
}
#[test]
fn snapshot_reads_without_draining() {
let q: EventQueue<u32> = EventQueue::new();
q.push(9);
assert_eq!(q.snapshot(), vec![9]);
assert_eq!(q.len(), 1);
}
}