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}