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