use core::sync::atomic::{AtomicBool, AtomicPtr, AtomicU32, Ordering};
const RING_CAPACITY: usize = 4096;
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct Observation {
pub instance_id: u32,
pub op_kind: u16,
pub flags: u16,
pub latency_ticks: u64,
pub producer_thread_id: u32,
pub _reserved: u32,
}
impl Observation {
pub const ZERO: Self = Self {
instance_id: 0,
op_kind: 0,
flags: 0,
latency_ticks: 0,
producer_thread_id: 0,
_reserved: 0,
};
}
#[inline]
pub fn thread_id() -> u32 {
thread_local! {
static TID: core::cell::Cell<u32> = const { core::cell::Cell::new(0) };
}
TID.with(|cell| {
let cached = cell.get();
if cached != 0 {
return cached;
}
static NEXT: AtomicU32 = AtomicU32::new(1);
let id = NEXT.fetch_add(1, Ordering::Relaxed);
let id = if id == 0 { NEXT.fetch_add(1, Ordering::Relaxed) } else { id };
cell.set(id);
id
})
}
pub static ARMED_COUNT: AtomicU32 = AtomicU32::new(0);
#[inline(always)]
pub fn any_observer_armed() -> bool {
ARMED_COUNT.load(Ordering::Relaxed) != 0
}
#[repr(C, align(64))]
pub struct ObservationRing {
head: AtomicU32,
_pad0: [u8; 60],
tail: AtomicU32,
armed: AtomicBool,
_pad_a: [u8; 3],
buf: AtomicPtr<core::cell::UnsafeCell<Observation>>,
_pad1: [u8; 48],
}
unsafe impl Sync for ObservationRing {}
impl ObservationRing {
pub const fn new() -> Self {
Self {
head: AtomicU32::new(0),
_pad0: [0; 60],
tail: AtomicU32::new(0),
armed: AtomicBool::new(false),
_pad_a: [0; 3],
buf: AtomicPtr::new(core::ptr::null_mut()),
_pad1: [0; 48],
}
}
#[inline]
fn buf_layout() -> std::alloc::Layout {
std::alloc::Layout::array::<core::cell::UnsafeCell<Observation>>(RING_CAPACITY)
.expect("observation buffer layout is valid")
}
#[inline(always)]
pub fn push(&self, obs: Observation) -> bool {
if ARMED_COUNT.load(Ordering::Relaxed) == 0 {
return false;
}
self.push_cold(obs)
}
#[inline(always)]
pub fn push_op(&self, op_kind: u16, flags: u16) -> bool {
if ARMED_COUNT.load(Ordering::Relaxed) == 0 {
return false;
}
self.push_cold(Observation { op_kind, flags, ..Observation::ZERO })
}
#[cold]
#[inline(never)]
fn push_cold(&self, mut obs: Observation) -> bool {
if !self.armed.load(Ordering::Relaxed) {
return false;
}
let buf = self.buf.load(Ordering::Acquire);
if buf.is_null() {
return false;
}
if obs.producer_thread_id == 0 {
obs.producer_thread_id = thread_id();
}
let tail = self.tail.load(Ordering::Relaxed);
let head = self.head.load(Ordering::Acquire);
let next = tail.wrapping_add(1);
if next.wrapping_sub(head) as usize > RING_CAPACITY {
return false;
}
let slot = (tail as usize) % RING_CAPACITY;
unsafe { *(*buf.add(slot)).get() = obs; }
self.tail.store(next, Ordering::Release);
true
}
pub fn pop(&self) -> Option<Observation> {
let buf = self.buf.load(Ordering::Acquire);
if buf.is_null() {
return None;
}
let head = self.head.load(Ordering::Relaxed);
let tail = self.tail.load(Ordering::Acquire);
if head == tail {
return None;
}
let slot = (head as usize) % RING_CAPACITY;
let obs = unsafe { *(*buf.add(slot)).get() };
self.head.store(head.wrapping_add(1), Ordering::Release);
Some(obs)
}
pub fn arm(&self) {
if self.buf.load(Ordering::Acquire).is_null() {
let layout = Self::buf_layout();
let ptr = unsafe { std::alloc::alloc_zeroed(layout) }
as *mut core::cell::UnsafeCell<Observation>;
if ptr.is_null() {
std::alloc::handle_alloc_error(layout);
}
if self
.buf
.compare_exchange(
core::ptr::null_mut(),
ptr,
Ordering::AcqRel,
Ordering::Acquire,
)
.is_err()
{
unsafe { std::alloc::dealloc(ptr as *mut u8, layout); }
}
}
if !self.armed.swap(true, Ordering::Release) {
ARMED_COUNT.fetch_add(1, Ordering::Relaxed);
}
}
#[inline]
pub fn is_armed(&self) -> bool {
self.armed.load(Ordering::Relaxed)
}
}
impl Default for ObservationRing {
fn default() -> Self {
Self::new()
}
}
impl Drop for ObservationRing {
fn drop(&mut self) {
if *self.armed.get_mut() {
ARMED_COUNT.fetch_sub(1, Ordering::Relaxed);
}
let buf = *self.buf.get_mut();
if !buf.is_null() {
unsafe { std::alloc::dealloc(buf as *mut u8, Self::buf_layout()); }
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn push_pop_roundtrip() {
let ring = ObservationRing::new();
ring.arm(); let obs = Observation { instance_id: 42, op_kind: 1, flags: 0, latency_ticks: 100, producer_thread_id: 0, _reserved: 0 };
assert!(ring.push(obs));
let got = ring.pop().unwrap();
assert_eq!(got.instance_id, 42);
assert_eq!(got.op_kind, 1);
assert_eq!(got.latency_ticks, 100);
assert_ne!(got.producer_thread_id, 0);
assert!(ring.pop().is_none());
}
#[test]
fn ring_fills_then_drops() {
let ring = ObservationRing::new();
ring.arm(); let obs = Observation::ZERO;
for _ in 0..RING_CAPACITY {
assert!(ring.push(obs));
}
assert!(!ring.push(obs));
}
#[test]
fn thread_id_stable_across_calls_from_same_thread() {
let a = thread_id();
let b = thread_id();
assert_eq!(a, b);
assert_ne!(a, 0, "thread_id must never return 0 (the sentinel)");
}
#[test]
fn thread_id_distinct_across_threads() {
use std::sync::mpsc;
let main_id = thread_id();
let (tx, rx) = mpsc::channel();
let t1 = std::thread::spawn(move || {
tx.send(thread_id()).unwrap();
});
let id1 = rx.recv().unwrap();
t1.join().unwrap();
assert_ne!(id1, main_id, "spawned thread must have distinct id");
assert_ne!(id1, 0);
}
#[test]
fn push_auto_stamps_thread_id_when_zero() {
let ring = ObservationRing::new();
ring.arm(); let obs = Observation {
instance_id: 1,
op_kind: 1,
flags: 0,
latency_ticks: 0,
producer_thread_id: 0,
_reserved: 0,
};
ring.push(obs);
let got = ring.pop().unwrap();
let me = thread_id();
assert_eq!(got.producer_thread_id, me);
}
#[test]
fn disarmed_ring_drops_push_until_armed() {
let ring = ObservationRing::new();
assert!(!ring.is_armed());
assert!(!ring.push(Observation::ZERO));
assert!(ring.pop().is_none());
ring.arm();
assert!(ring.is_armed());
assert!(ring.push(Observation::ZERO));
assert!(ring.pop().is_some());
}
#[test]
fn push_preserves_explicit_thread_id() {
let ring = ObservationRing::new();
ring.arm(); let obs = Observation {
instance_id: 1,
op_kind: 1,
flags: 0,
latency_ticks: 0,
producer_thread_id: 42,
_reserved: 0,
};
ring.push(obs);
let got = ring.pop().unwrap();
assert_eq!(got.producer_thread_id, 42, "explicit tid should not be overwritten");
}
}