Skip to main content

themis/law/
identity.rs

1//! Placement identity newtypes.
2
3/// NUMA node identity.
4#[repr(transparent)]
5#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub struct NumaNodeId(u32);
7
8impl NumaNodeId {
9    /// Node zero.
10    pub const ZERO: Self = Self(0);
11
12    /// Sentinel representing an invalid/unknown node.
13    pub const INVALID: Self = Self(u32::MAX);
14
15    /// Creates a NUMA node identifier.
16    #[must_use]
17    pub const fn new(raw: u32) -> Self {
18        Self(raw)
19    }
20
21    /// Returns the raw node value.
22    #[must_use]
23    pub const fn get(self) -> u32 {
24        self.0
25    }
26
27    /// Returns the node as an index.
28    #[must_use]
29    pub const fn index(self) -> usize {
30        self.0 as usize
31    }
32
33    /// Returns true when the node identifier is valid.
34    #[must_use]
35    #[inline]
36    pub const fn is_valid(self) -> bool {
37        self.0 != Self::INVALID.0
38    }
39
40    /// Maps this NUMA node into a fixed-size bucket table.
41    #[must_use]
42    pub const fn bucket_index<const BUCKETS: usize>(self) -> NumaBucketIndex<BUCKETS> {
43        NumaBucketIndex::new(self.index())
44    }
45}
46
47/// NUMA bucket identity for a fixed-size placement table.
48#[repr(transparent)]
49#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
50pub struct NumaBucketIndex<const BUCKETS: usize>(usize);
51
52impl<const BUCKETS: usize> NumaBucketIndex<BUCKETS> {
53    const ASSERT_NONZERO: () = {
54        assert!(BUCKETS > 0, "NUMA bucket count must be non-zero");
55    };
56
57    /// Creates a bucket index from an already-normalized raw index.
58    #[must_use]
59    pub const fn new(raw: usize) -> Self {
60        let () = Self::ASSERT_NONZERO;
61        Self(raw % BUCKETS)
62    }
63
64    /// Returns the normalized bucket index.
65    #[must_use]
66    pub const fn index(self) -> usize {
67        self.0
68    }
69
70    /// Returns the next bucket after `offset` positions, wrapping inside the bucket table.
71    #[must_use]
72    pub const fn wrapping_add(self, offset: usize) -> Self {
73        let () = Self::ASSERT_NONZERO;
74        let offset = offset % BUCKETS;
75        let remaining = BUCKETS - self.0;
76        if offset < remaining {
77            Self(self.0 + offset)
78        } else {
79            Self(offset - remaining)
80        }
81    }
82}
83
84/// Scheduler worker identity.
85#[repr(transparent)]
86#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
87pub struct WorkerId(u32);
88
89impl WorkerId {
90    /// Sentinel representing an invalid/unknown worker.
91    pub const INVALID: Self = Self(u32::MAX);
92
93    /// Creates a worker identifier.
94    #[must_use]
95    pub const fn new(raw: u32) -> Self {
96        Self(raw)
97    }
98
99    /// Returns the raw worker value.
100    #[must_use]
101    pub const fn get(self) -> u32 {
102        self.0
103    }
104
105    /// Returns the worker as an index.
106    #[must_use]
107    pub const fn index(self) -> usize {
108        self.0 as usize
109    }
110
111    /// Returns true when the worker identifier is valid.
112    #[must_use]
113    #[inline]
114    pub const fn is_valid(self) -> bool {
115        self.0 != Self::INVALID.0
116    }
117}
118
119/// Coarse memory locality domain.
120#[repr(transparent)]
121#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
122pub struct LocalityDomainId(u32);
123
124impl LocalityDomainId {
125    /// Sentinel representing an invalid/unknown locality domain.
126    pub const INVALID: Self = Self(u32::MAX);
127
128    /// Creates a locality domain identifier.
129    #[must_use]
130    pub const fn new(raw: u32) -> Self {
131        Self(raw)
132    }
133
134    /// Returns the raw domain value.
135    #[must_use]
136    pub const fn get(self) -> u32 {
137        self.0
138    }
139
140    /// Returns true when the locality domain identifier is valid.
141    #[must_use]
142    #[inline]
143    pub const fn is_valid(self) -> bool {
144        self.0 != Self::INVALID.0
145    }
146}