use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Mutex;
use super::RING_CAPACITY;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RawSample {
pub os_tid: u64,
pub since_start_nanos: u64,
pub stack: Vec<u64>,
pub truncated: bool,
}
#[derive(Debug)]
pub struct SampleRing {
samples: Mutex<Vec<RawSample>>,
capacity: usize,
dropped: AtomicU64,
accepted: AtomicU64,
}
impl Default for SampleRing {
fn default() -> Self {
Self::with_capacity(RING_CAPACITY)
}
}
impl SampleRing {
pub fn with_capacity(capacity: usize) -> Self {
Self {
samples: Mutex::new(Vec::with_capacity(capacity.min(1024))),
capacity,
dropped: AtomicU64::new(0),
accepted: AtomicU64::new(0),
}
}
pub fn push(&self, sample: RawSample) -> bool {
let mut samples = self.samples.lock().unwrap_or_else(|e| e.into_inner());
if samples.len() >= self.capacity {
self.dropped.fetch_add(1, Ordering::Relaxed);
return false;
}
samples.push(sample);
self.accepted.fetch_add(1, Ordering::Relaxed);
true
}
pub fn drain(&self) -> Vec<RawSample> {
let mut samples = self.samples.lock().unwrap_or_else(|e| e.into_inner());
std::mem::take(&mut *samples)
}
pub fn dropped(&self) -> u64 {
self.dropped.load(Ordering::Relaxed)
}
pub fn accepted(&self) -> u64 {
self.accepted.load(Ordering::Relaxed)
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn is_full(&self) -> bool {
self.len() >= self.capacity
}
pub fn len(&self) -> usize {
self.samples.lock().unwrap_or_else(|e| e.into_inner()).len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}