use core::borrow::Borrow;
#[cfg(not(feature = "nightly"))]
use core::cell::Cell;
use core::ops::Deref;
use std::thread::ThreadId;
use cfg_if::cfg_if;
use equivalent::Equivalent;
#[cfg(not(feature = "nightly"))]
fast_thread_local! {
static STD_TID: Cell<Option<StdThreadId>> = Cell::new(None);
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "nightly-docs", doc(cfg(feature = "std")))]
#[must_use]
#[repr(transparent)]
pub struct StdThreadId(pub ThreadId);
impl StdThreadId {
#[inline]
pub fn current() -> Self {
cfg_if! {
if #[cfg(feature = "nightly")] {
StdThreadId(std::thread::current_id())
} else {
STD_TID.with(|cell| match cell.get() {
None => {
let new_id = Self::acquire();
cell.set(Some(new_id));
new_id
}
Some(existing) => existing,
})
}
}
}
}
#[cfg_attr(feature = "nightly-docs", doc(cfg(feature = "std")))]
unsafe impl crate::IThreadId for StdThreadId {
#[inline]
fn current() -> StdThreadId {
<Self>::current()
}
}
#[cfg(feature = "bytemuck")]
#[cfg_attr(feature = "nightly-docs", doc(cfg(feature = "bytemuck")))]
unsafe impl bytemuck::TransparentWrapper<ThreadId> for StdThreadId {}
unsafe impl crate::IThreadId for ThreadId {
#[inline]
fn current() -> Self {
StdThreadId::current().0
}
}
impl StdThreadId {
#[cold]
#[cfg(not(feature = "nightly"))]
fn acquire() -> StdThreadId {
StdThreadId(std::thread::current().id())
}
}
impl From<ThreadId> for StdThreadId {
#[inline]
fn from(value: ThreadId) -> Self {
StdThreadId(value)
}
}
impl From<StdThreadId> for ThreadId {
#[inline]
fn from(value: StdThreadId) -> Self {
value.0
}
}
impl Borrow<ThreadId> for StdThreadId {
fn borrow(&self) -> &ThreadId {
&self.0
}
}
impl AsRef<ThreadId> for StdThreadId {
#[inline]
fn as_ref(&self) -> &ThreadId {
&self.0
}
}
impl Deref for StdThreadId {
type Target = ThreadId;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl PartialEq<ThreadId> for StdThreadId {
#[inline]
fn eq(&self, other: &ThreadId) -> bool {
self.0 == *other
}
}
impl Equivalent<ThreadId> for StdThreadId {
#[inline]
fn equivalent(&self, key: &ThreadId) -> bool {
*key == self.0
}
}
#[cfg(feature = "slog")]
#[cfg_attr(feature = "nightly-docs", doc(cfg(feature = "slog")))]
impl slog::Value for StdThreadId {
fn serialize(&self, _record: &slog::Record, key: slog::Key, serializer: &mut dyn slog::Serializer) -> slog::Result {
serializer.emit_arguments(key, &format_args!("{self:?}"))
}
}