Skip to main content

atomic_tagged_ptr/
tag.rs

1use core::fmt;
2
3use crate::TAG_MASK;
4
5/// Represents a generation tag used for ABA protection in `AtomicTaggedPtr`.
6///
7/// `Tag` wraps a platform-specific generation count and ensures that any operations
8/// (like wrapping addition or creation) respect the hardware platform's limits and bit-width.
9#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct Tag(pub(crate) usize);
11
12impl Tag {
13    /// Creates a new `Tag` from a raw value, applying the platform-specific mask.
14    #[inline]
15    pub const fn new(value: usize) -> Self {
16        Self(value & TAG_MASK)
17    }
18
19    /// Gets the raw tag value.
20    #[inline]
21    pub const fn value(self) -> usize {
22        self.0
23    }
24
25    /// Performs wrapping addition on the tag value.
26    #[inline]
27    pub const fn wrapping_add(self, rhs: usize) -> Self {
28        Self::new(self.0.wrapping_add(rhs))
29    }
30
31    /// Performs wrapping subtraction on the tag value.
32    #[inline]
33    pub const fn wrapping_sub(self, rhs: usize) -> Self {
34        Self::new(self.0.wrapping_sub(rhs))
35    }
36
37    /// Returns the next tag value, wrapping around on overflow.
38    #[inline]
39    pub const fn next(self) -> Self {
40        self.wrapping_add(1)
41    }
42
43    /// Returns the maximum tag value allowed on this platform.
44    #[inline]
45    pub const fn max_value() -> Self {
46        Self(TAG_MASK)
47    }
48}
49
50impl fmt::Debug for Tag {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        write!(f, "Tag({:#X})", self.0)
53    }
54}
55
56impl fmt::Display for Tag {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        write!(f, "{}", self.0)
59    }
60}
61
62impl From<usize> for Tag {
63    #[inline]
64    fn from(value: usize) -> Self {
65        Self::new(value)
66    }
67}
68
69impl From<u8> for Tag {
70    #[inline]
71    fn from(value: u8) -> Self {
72        Self::new(value as usize)
73    }
74}
75
76impl From<u16> for Tag {
77    #[inline]
78    fn from(value: u16) -> Self {
79        Self::new(value as usize)
80    }
81}
82
83impl From<u32> for Tag {
84    #[inline]
85    fn from(value: u32) -> Self {
86        Self::new(value as usize)
87    }
88}
89
90impl From<Tag> for usize {
91    #[inline]
92    fn from(tag: Tag) -> usize {
93        tag.0
94    }
95}
96
97impl core::ops::Add<usize> for Tag {
98    type Output = Self;
99
100    #[inline]
101    fn add(self, rhs: usize) -> Self::Output {
102        self.wrapping_add(rhs)
103    }
104}
105
106impl core::ops::AddAssign<usize> for Tag {
107    #[inline]
108    fn add_assign(&mut self, rhs: usize) {
109        *self = *self + rhs;
110    }
111}
112
113impl core::ops::Sub<usize> for Tag {
114    type Output = Self;
115
116    #[inline]
117    fn sub(self, rhs: usize) -> Self::Output {
118        self.wrapping_sub(rhs)
119    }
120}
121
122impl core::ops::SubAssign<usize> for Tag {
123    #[inline]
124    fn sub_assign(&mut self, rhs: usize) {
125        *self = *self - rhs;
126    }
127}
128
129impl core::ops::BitAnd<usize> for Tag {
130    type Output = Self;
131
132    #[inline]
133    fn bitand(self, rhs: usize) -> Self::Output {
134        Self::new(self.0 & rhs)
135    }
136}
137
138impl core::ops::BitAnd<Tag> for Tag {
139    type Output = Self;
140
141    #[inline]
142    fn bitand(self, rhs: Tag) -> Self::Output {
143        Self::new(self.0 & rhs.0)
144    }
145}
146
147impl core::ops::BitAndAssign<usize> for Tag {
148    #[inline]
149    fn bitand_assign(&mut self, rhs: usize) {
150        *self = *self & rhs;
151    }
152}
153
154impl core::ops::BitAndAssign<Tag> for Tag {
155    #[inline]
156    fn bitand_assign(&mut self, rhs: Tag) {
157        *self = *self & rhs.0;
158    }
159}
160
161impl core::ops::BitOr<usize> for Tag {
162    type Output = Self;
163
164    #[inline]
165    fn bitor(self, rhs: usize) -> Self::Output {
166        Self::new(self.0 | rhs)
167    }
168}
169
170impl core::ops::BitOr<Tag> for Tag {
171    type Output = Self;
172
173    #[inline]
174    fn bitor(self, rhs: Tag) -> Self::Output {
175        Self::new(self.0 | rhs.0)
176    }
177}
178
179impl core::ops::BitOrAssign<usize> for Tag {
180    #[inline]
181    fn bitor_assign(&mut self, rhs: usize) {
182        *self = *self | rhs;
183    }
184}
185
186impl core::ops::BitOrAssign<Tag> for Tag {
187    #[inline]
188    fn bitor_assign(&mut self, rhs: Tag) {
189        *self = *self | rhs.0;
190    }
191}
192
193impl core::ops::BitXor<usize> for Tag {
194    type Output = Self;
195
196    #[inline]
197    fn bitxor(self, rhs: usize) -> Self::Output {
198        Self::new(self.0 ^ rhs)
199    }
200}
201
202impl core::ops::BitXor<Tag> for Tag {
203    type Output = Self;
204
205    #[inline]
206    fn bitxor(self, rhs: Tag) -> Self::Output {
207        Self::new(self.0 ^ rhs.0)
208    }
209}
210
211impl core::ops::BitXorAssign<usize> for Tag {
212    #[inline]
213    fn bitxor_assign(&mut self, rhs: usize) {
214        *self = *self ^ rhs;
215    }
216}
217
218impl core::ops::BitXorAssign<Tag> for Tag {
219    #[inline]
220    fn bitxor_assign(&mut self, rhs: Tag) {
221        *self = *self ^ rhs.0;
222    }
223}
224
225impl core::ops::Not for Tag {
226    type Output = Self;
227
228    #[inline]
229    fn not(self) -> Self::Output {
230        Self::new(!self.0)
231    }
232}