Skip to main content

kithara_events/
ids.rs

1#![forbid(unsafe_code)]
2
3use core::sync::atomic::{AtomicU64, Ordering};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6pub struct SlotId(u64);
7
8impl SlotId {
9    #[must_use]
10    pub const fn new(value: u64) -> Self {
11        Self(value)
12    }
13
14    #[must_use]
15    pub const fn value(self) -> u64 {
16        self.0
17    }
18}
19
20/// Monotonic identifier for a track across the entire process.
21///
22/// Allocated from a single global counter so [`Queue`](crate::queue) and
23/// FFI items share one address space — the value `audioId` reports
24/// over the FFI boundary is exactly the value the queue uses
25/// internally. Stable across removals: removing a track and adding a
26/// new one yields a fresh id.
27#[derive(
28    Clone,
29    Copy,
30    Debug,
31    PartialEq,
32    Eq,
33    Hash,
34    PartialOrd,
35    Ord,
36    derive_more::From,
37    derive_more::Display,
38)]
39#[display("{_0}")]
40pub struct TrackId(pub u64);
41
42impl From<TrackId> for u64 {
43    fn from(id: TrackId) -> Self {
44        id.0
45    }
46}
47
48impl TrackId {
49    /// Allocate the next monotonic id from the process-wide counter.
50    ///
51    /// This is the single allocation site: the FFI item layer reserves
52    /// an id at construction so caller-visible `audioId` is stable from
53    /// day one, and `Queue::insert` consumes that same id without
54    /// re-allocating. The counter starts at `0` and is never reset.
55    #[must_use]
56    pub fn allocate() -> Self {
57        static NEXT: AtomicU64 = AtomicU64::new(0);
58        Self(NEXT.fetch_add(1, Ordering::Relaxed))
59    }
60
61    /// Raw id value.
62    #[must_use]
63    pub const fn as_u64(self) -> u64 {
64        self.0
65    }
66}