1#[macro_export]
3macro_rules! runtime_token {
4($vis: vis $id: ident) => {
5 $crate::paste! {
6 $vis use [<__ $id _mod__ >]::$id;
7 #[allow(nonstandard_style)]
8 mod [<__ $id _mod__ >] {
9 use $crate::core::TokenCell;
10 use core::{convert::Infallible, sync::atomic::AtomicU16};
11 static COUNTER: AtomicU16 = AtomicU16::new(0);
12 pub struct $id(u16);
14 impl $crate::core::TokenTrait for $id {
15 type ConstructionError = Infallible;
16 type RunError = Infallible;
17 type Identifier = u16;
18 type ComparisonError = $crate::macros::IdMismatch;
19 type Branded<'a> = Self;
20 fn new() -> Result<Self, Self::ConstructionError> {
21 Ok($id(
22 COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed),
23 ))
24 }
25 fn with_token<R, F: FnOnce(Self)->R>(f: F) -> Result<R, Self::RunError> {
26 Self::new().map(f)
27 }
28 fn identifier(&self) -> Self::Identifier {
29 self.0
30 }
31 fn compare(&self, id: &Self::Identifier) -> Result<(), Self::ComparisonError> {
32 if self.0 == *id {
33 Ok(())
34 } else {
35 Err($crate::macros::IdMismatch {
36 cell: *id,
37 token: self.0,
38 })
39 }
40 }
41 }
42 }
43 }
44};
45($($vis: vis $id: ident),*) => {
46 $($crate::runtime_token!($vis $id);)*
47}
48}
49
50#[macro_export]
54macro_rules! singleton_token {
55($vis: vis $id: ident) => {
56 $crate::paste! {
57 $vis use [<__ $id _mod__ >]::$id;
58 #[allow(nonstandard_style)]
59 mod [<__ $id _mod__ >] {
60 use core::{convert::Infallible, sync::atomic::AtomicBool};
61 use $crate::SingletonUnavailable;
62 static AVAILABLE: AtomicBool = AtomicBool::new(true);
63 pub struct $id(());
67 impl $crate::core::TokenTrait for $id {
68 type ConstructionError = SingletonUnavailable;
69 type RunError = SingletonUnavailable;
70 type Identifier = ();
71 type ComparisonError = Infallible;
72 fn new() -> Result<Self, Self::ConstructionError> {
73 if AVAILABLE.swap(false, core::sync::atomic::Ordering::Relaxed) {
74 Ok($id(()))
75 } else {
76 Err(SingletonUnavailable)
77 }
78 }
79 fn with_token<R, F: FnOnce(Self)->R>(f: F) -> Result<R, Self::RunError> {
80 Self::new().map(f)
81 }
82 fn identifier(&self) -> Self::Identifier {
83 self.0
84 }
85 fn compare(&self, _: &Self::Identifier) -> Result<(), Self::ComparisonError> {
86 Ok(())
87 }
88 }
89 impl ::core::ops::Drop for $id {
90 fn drop(&mut self) {
91 AVAILABLE.store(true, core::sync::atomic::Ordering::Relaxed);
92 }
93 }
94 }
95 }
96};
97($($vis: vis $id: ident),*) => {
98 $($crate::singleton_token!($vis $id);)*
99}
100}
101
102#[macro_export]
108macro_rules! unsafe_token {
109($vis: vis $id: ident) => {
110 $crate::paste! {
111 $vis use [<__ $id _mod__ >]::$id;
112 #[allow(nonstandard_style)]
113 mod [<__ $id _mod__ >] {
114 use core::convert::Infallible;
115 pub struct $id(());
121 impl $crate::core::TokenTrait for $id {
122 type ConstructionError = Infallible;
123 type RunError = Infallible;
124 type Identifier = ();
125 type ComparisonError = Infallible;
126 type Branded<'a> = Self;
127 fn new() -> Result<Self, Self::ConstructionError> {
128 Ok($id(()))
129 }
130 fn with_token<R, F: FnOnce(Self)->R>(f: F) -> Result<R, Self::RunError> {
131 Self::new().map(f)
132 }
133 fn identifier(&self) -> Self::Identifier {
134 self.0
135 }
136 fn compare(&self, _: &Self::Identifier) -> Result<(), Self::ComparisonError> {
137 Ok(())
138 }
139 }
140 }
141 }
142};
143($($vis: vis $id: ident),*) => {
144 $($crate::unsafe_token!($vis $id);)*
145}
146}
147pub use token::token;
148#[cfg(any(feature = "debug", debug_assertions))]
149mod token {
150 pub use crate::runtime_token as token;
151}
152#[cfg(not(any(feature = "debug", debug_assertions)))]
153mod token {
154 pub use crate::unsafe_token as token;
155}
156
157#[derive(Debug, Clone, Copy)]
159pub struct IdMismatch {
160 pub cell: u16,
162 pub token: u16,
164}
165impl ::core::fmt::Display for IdMismatch {
166 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
167 write!(f, "{:?}", self)
168 }
169}
170#[derive(Debug, Clone, Copy)]
172pub struct SingletonUnavailable;
173impl ::core::fmt::Display for SingletonUnavailable {
174 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
175 write!(f, "{:?}", self)
176 }
177}