libdd_profiling/internal/profile/interning_api/
generational_ids.rs

1// Copyright 2025-Present Datadog, Inc. https://www.datadoghq.com/
2// SPDX-License-Identifier: Apache-2.0
3
4use std::sync::atomic::AtomicU64;
5
6/// Opaque identifier for the profiler generation
7#[derive(Clone, Copy, PartialEq, Eq)]
8#[repr(C)]
9pub struct Generation {
10    id: u64,
11}
12
13impl Generation {
14    const IMMORTAL: Self = Self { id: u64::MAX };
15
16    /// The only way to create a generation.  Guaranteed to give a new value each time.
17    pub fn new() -> Self {
18        static COUNTER: AtomicU64 = AtomicU64::new(0);
19        Self {
20            id: COUNTER.fetch_add(1, std::sync::atomic::Ordering::SeqCst),
21        }
22    }
23}
24impl Default for Generation {
25    fn default() -> Self {
26        Self::new()
27    }
28}
29
30#[repr(C)]
31pub struct GenerationalId<T: Copy> {
32    generation: Generation,
33    id: T,
34}
35
36impl<T: Copy> GenerationalId<T> {
37    pub fn get(&self, expected_generation: Generation) -> anyhow::Result<T> {
38        anyhow::ensure!(
39            self.generation == expected_generation || self.generation == Generation::IMMORTAL
40        );
41        Ok(self.id)
42    }
43
44    pub const fn new(id: T, generation: Generation) -> Self {
45        Self { id, generation }
46    }
47
48    pub const fn new_immortal(id: T) -> Self {
49        Self {
50            id,
51            generation: Generation::IMMORTAL,
52        }
53    }
54}