#[macro_export]
macro_rules! singleton_token {
($(#[$meta: meta])* $vis: vis $id: ident) => {
$crate::paste! {
$vis use [<__ $id _mod__ >]::$id;
#[allow(nonstandard_style)]
mod [<__ $id _mod__ >] {
use core::{convert::Infallible, sync::atomic::AtomicBool};
use $crate::SingletonUnavailable;
static AVAILABLE: AtomicBool = AtomicBool::new(true);
$(#[$meta])*
#[derive(::core::fmt::Debug)]
pub struct $id(());
impl $crate::core::UnscopedToken for $id {
type ConstructionError = SingletonUnavailable;
fn try_new() -> Result<Self, Self::ConstructionError> {
if AVAILABLE.swap(false, core::sync::atomic::Ordering::Relaxed) {
Ok($id(()))
} else {
Err(SingletonUnavailable)
}
}
}
impl ::core::ops::Drop for $id {
fn drop(&mut self) {
AVAILABLE.store(true, core::sync::atomic::Ordering::Relaxed);
}
}
impl $crate::core::TokenTrait for $id {
type ComparisonMaySpuriouslyEq = $crate::core::False;
type RunError = SingletonUnavailable;
type Identifier = ();
type ComparisonError = Infallible;
fn with_token<R, F: FnOnce(Self)->R>(f: F) -> Result<R, Self::RunError> {
Self::try_new().map(f)
}
fn identifier(&self) -> Self::Identifier {
self.0
}
fn compare(&self, _: &Self::Identifier) -> Result<(), Self::ComparisonError> {
Ok(())
}
}
impl ::core::ops::Drop for $id {
fn drop(&mut self) {
AVAILABLE.store(true, core::sync::atomic::Ordering::Relaxed);
}
}
}
}
};
($($(#[$meta: meta])* $vis: vis $id: ident),*) => {
$($crate::singleton_token!($(#[$meta])* $vis $id);)*
}
}
#[macro_export]
macro_rules! unsafe_token {
($(#[$meta: meta])* $vis: vis $id: ident) => {
$crate::paste! {
$vis use [<__ $id _mod__ >]::$id;
#[allow(nonstandard_style)]
mod [<__ $id _mod__ >] {
use core::convert::Infallible;
use $crate::core::UnscopedToken;
$(#[$meta])*
#[derive(::core::fmt::Debug)]
pub struct $id(());
impl UnscopedToken for $id {
type ConstructionError = Infallible;
fn try_new() -> Result<Self, Self::ConstructionError> {
Ok(Self(()))
}
}
impl $crate::core::TokenTrait for $id {
type ComparisonMaySpuriouslyEq = $crate::core::True;
type RunError = Infallible;
type Identifier = ();
type ComparisonError = Infallible;
type Branded<'a> = Self;
fn with_token<R, F: FnOnce(Self)->R>(f: F) -> Result<R, Self::RunError> {
Ok(f(Self::new()))
}
fn identifier(&self) -> Self::Identifier {
self.0
}
fn compare(&self, _: &Self::Identifier) -> Result<(), Self::ComparisonError> {
Ok(())
}
}
}
}
};
($($(#[$meta: meta])* $vis: vis $id: ident),*) => {
$($crate::unsafe_token!($(#[$meta])* $vis $id);)*
}
}
pub use token::token;
#[cfg(any(feature = "debug", debug_assertions))]
mod token {
pub use crate::runtime_token as token;
}
#[cfg(not(any(feature = "debug", debug_assertions)))]
mod token {
pub use crate::unsafe_token as token;
}
#[derive(Debug, Clone, Copy)]
pub struct SingletonUnavailable;
impl ::core::fmt::Display for SingletonUnavailable {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
write!(f, "{:?}", self)
}
}