use std::cell::RefCell;
use tracing_core::span;
thread_local! {
static SCOPE_GUARDS: RefCell<Vec<(u64, dcontext::ScopeGuard)>> = RefCell::new(Vec::new());
}
pub(crate) fn push_guard(id: &span::Id, guard: dcontext::ScopeGuard) {
SCOPE_GUARDS.with(|stack| {
stack.borrow_mut().push((id.into_u64(), guard));
});
}
pub(crate) fn pop_guard(id: &span::Id) {
SCOPE_GUARDS.with(|stack| {
let mut stack = stack.borrow_mut();
let target = id.into_u64();
if let Some(pos) = stack.iter().rposition(|(sid, _)| *sid == target) {
stack.remove(pos);
}
});
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn push_pop_single() {
let _guard = dcontext::enter_scope();
let id = span::Id::from_u64(1);
let scope_guard = dcontext::enter_scope();
push_guard(&id, scope_guard);
SCOPE_GUARDS.with(|s| assert_eq!(s.borrow().len(), 1));
pop_guard(&id);
SCOPE_GUARDS.with(|s| assert!(s.borrow().is_empty()));
}
#[test]
fn push_pop_nested() {
let _guard = dcontext::enter_scope();
let id1 = span::Id::from_u64(1);
let id2 = span::Id::from_u64(2);
push_guard(&id1, dcontext::enter_scope());
push_guard(&id2, dcontext::enter_scope());
SCOPE_GUARDS.with(|s| assert_eq!(s.borrow().len(), 2));
pop_guard(&id2);
SCOPE_GUARDS.with(|s| assert_eq!(s.borrow().len(), 1));
pop_guard(&id1);
SCOPE_GUARDS.with(|s| assert!(s.borrow().is_empty()));
}
#[test]
fn pop_nonexistent_is_noop() {
let id = span::Id::from_u64(99);
pop_guard(&id); }
}