use std::cell::{Cell, UnsafeCell};
use std::sync::atomic::{AtomicU64, Ordering::Relaxed};
use crate::driver::EventMessage;
use crate::record::SpanRecord;
pub(crate) const ID_BATCH: u64 = 1024;
pub(crate) static NEXT_THREAD_KEY: AtomicU64 = AtomicU64::new(0);
#[derive(Clone, Copy, Debug)]
pub(crate) struct StackedSpan {
pub tracing_id: u64,
pub actual_id: u64,
}
pub(crate) struct ThreadSenders {
pub(crate) cache_addr: usize,
pub(crate) span: spillway::Sender<SpanRecord>,
pub(crate) event: spillway::Sender<EventMessage>,
}
thread_local! {
pub(crate) static SPAN_STACK: UnsafeCell<Vec<StackedSpan>> =
const { UnsafeCell::new(Vec::new()) };
pub(crate) static PENDING_SPAN: UnsafeCell<Vec<SpanRecord>> =
const { UnsafeCell::new(Vec::new()) };
pub(crate) static PENDING_EVENT: UnsafeCell<Vec<EventMessage>> =
const { UnsafeCell::new(Vec::new()) };
pub(crate) static THREAD_SHARD_KEY: Cell<u64> = const { Cell::new(u64::MAX) };
pub(crate) static THREAD_SENDERS: UnsafeCell<Option<ThreadSenders>>
= const { UnsafeCell::new(None) };
pub(crate) static ID_CURSOR: Cell<u64> = const { Cell::new(0) };
}
#[inline]
pub(crate) fn stack_top() -> Option<StackedSpan> {
SPAN_STACK.with(|c| unsafe { (*c.get()).last().copied() })
}
#[inline]
pub(crate) fn stack_push(entry: StackedSpan) {
SPAN_STACK.with(|c| unsafe { (*c.get()).push(entry) });
}
#[inline]
pub(crate) fn stack_pop() {
SPAN_STACK.with(|c| unsafe {
(*c.get()).pop();
});
}
#[inline]
pub(crate) fn pending_push_span(record: SpanRecord) -> usize {
PENDING_SPAN.with(|c| unsafe {
let v = &mut *c.get();
v.push(record);
v.len()
})
}
#[inline]
pub(crate) fn pending_push_event(msg: EventMessage) -> usize {
PENDING_EVENT.with(|c| unsafe {
let v = &mut *c.get();
v.push(msg);
v.len()
})
}
#[inline]
pub(crate) fn pending_drain_spans<F: FnMut(std::vec::Drain<'_, SpanRecord>)>(mut f: F) {
PENDING_SPAN.with(|c| unsafe {
f((*c.get()).drain(..));
});
}
#[inline]
pub(crate) fn pending_drain_events<F: FnMut(std::vec::Drain<'_, EventMessage>)>(mut f: F) {
PENDING_EVENT.with(|c| unsafe {
f((*c.get()).drain(..));
});
}
#[inline]
pub(crate) fn ensure_thread_shard_key() -> u64 {
THREAD_SHARD_KEY.with(|c| {
let v = c.get();
if v == u64::MAX {
let assigned = NEXT_THREAD_KEY.fetch_add(1, Relaxed);
c.set(assigned);
assigned
} else {
v
}
})
}