use std::sync::atomic::{AtomicU32, Ordering}; pub fn atomic_inc(c: &AtomicU32) -> u32 { c.fetch_add(1, Ordering::Relaxed) } pub fn atomic_dec(c: &AtomicU32) -> u32 { c.fetch_sub(1, Ordering::Relaxed) } // Used during debugging to see if some locks take too long. #[cfg(not(feature = "timed_existence"))] mod timed_existence { use std::ops::{Deref, DerefMut}; pub struct TimedExistence(T); impl TimedExistence { #[inline(always)] pub fn new(object: T, _reason: &'static str) -> Self { Self(object) } } impl Deref for TimedExistence { type Target = T; #[inline(always)] fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for TimedExistence { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } #[inline(always)] pub fn timeit(_n: impl std::fmt::Display, f: impl FnOnce() -> R) -> R { f() } } #[cfg(feature = "timed_existence")] mod timed_existence { use std::ops::{Deref, DerefMut}; use std::time::{Duration, Instant}; use tracing::warn; const MAX: Duration = Duration::from_millis(1); // Prints if the object exists for too long. // This is used to track long-lived locks for debugging. pub struct TimedExistence { object: T, reason: &'static str, started: Instant, } impl TimedExistence { pub fn new(object: T, reason: &'static str) -> Self { Self { object, reason, started: Instant::now(), } } } impl Drop for TimedExistence { fn drop(&mut self) { let elapsed = self.started.elapsed(); let reason = self.reason; tracing::trace!(name=%self.reason, ?elapsed, "dropping guard"); if elapsed > MAX { warn!("elapsed on lock {reason:?}: {elapsed:?}") } } } impl Deref for TimedExistence { type Target = T; fn deref(&self) -> &Self::Target { &self.object } } impl DerefMut for TimedExistence { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.object } } pub fn timeit(name: impl std::fmt::Display, f: impl FnOnce() -> R) -> R { let now = Instant::now(); tracing::trace!(%name, "starting"); let r = f(); tracing::trace!(%name, "done"); let elapsed = now.elapsed(); if elapsed > MAX { warn!(%name, ?elapsed, max = ?MAX, "elapsed > MAX"); } r } } pub use timed_existence::{timeit, TimedExistence};