use core::cell::Cell;
use core::fmt;
use core::marker::PhantomData;
use core::num::NonZeroU64;
use core::ops::Deref;
use core::sync::atomic::{AtomicU64, Ordering};
static NEXT_ID: AtomicU64 = AtomicU64::new(1);
std::thread_local! {
static THREAD_ID: Cell<u64> = const { Cell::new(0) };
}
fn fresh_id() -> NonZeroU64 {
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
NonZeroU64::new(id).unwrap_or(NonZeroU64::MIN)
}
pub struct Owner {
id: NonZeroU64,
_not_sync: PhantomData<Cell<()>>,
}
impl Owner {
pub fn new() -> Self {
Self {
id: fresh_id(),
_not_sync: PhantomData,
}
}
pub fn thread() -> ThreadOwner {
let id = THREAD_ID.with(|slot| match NonZeroU64::new(slot.get()) {
Some(id) => id,
None => {
let id = fresh_id();
slot.set(id.get());
id
}
});
ThreadOwner {
owner: Self {
id,
_not_sync: PhantomData,
},
_not_send: PhantomData,
}
}
pub(super) fn id(&self) -> u64 {
self.id.get()
}
}
impl Default for Owner {
fn default() -> Self {
Self::new()
}
}
impl fmt::Debug for Owner {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Owner").field(&self.id).finish()
}
}
pub struct ThreadOwner {
owner: Owner,
_not_send: PhantomData<*const ()>,
}
impl Deref for ThreadOwner {
type Target = Owner;
fn deref(&self) -> &Owner {
&self.owner
}
}
impl fmt::Debug for ThreadOwner {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("ThreadOwner").field(&self.owner.id).finish()
}
}