From 16d6bd7ece4c4b9b72f6bd51c9b034270b745525 Mon Sep 17 00:00:00 2001 From: Mica White Date: Sun, 13 Sep 2026 15:12:08 -0400 Subject: Support no_std --- src/key.rs | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) (limited to 'src/key.rs') diff --git a/src/key.rs b/src/key.rs index c788b32..06f219b 100755 --- a/src/key.rs +++ b/src/key.rs @@ -1,6 +1,7 @@ -use std::cell::{Cell, LazyCell}; -use std::fmt::{self, Debug}; -use std::marker::PhantomData; +#[cfg(feature = "std")] +use core::cell::Cell; +use core::fmt::{self, Debug}; +use core::marker::PhantomData; use sealed::Sealed; @@ -14,8 +15,9 @@ mod sealed { impl Sealed for &mut ThreadKey {} } +#[cfg(feature = "std")] thread_local! { - static KEY: LazyCell = LazyCell::new(KeyCell::default); + static KEY: std::cell::LazyCell = std::cell::LazyCell::new(KeyCell::default); } /// The key for the current thread. @@ -55,7 +57,10 @@ impl Drop for ThreadKey { fn drop(&mut self) { // safety: a thread key cannot be acquired without creating the lock // safety: the key is lost, so it's safe to unlock the cell - unsafe { KEY.with(|key| key.force_unlock()) } + #[cfg(feature = "std")] + unsafe { + KEY.with(|key| key.force_unlock()) + } } } @@ -74,6 +79,7 @@ impl ThreadKey { /// let key = ThreadKey::get().unwrap(); /// ``` #[must_use] + #[cfg(feature = "std")] pub fn get() -> Option { // if this code changes, check to ensure the requirement for // the Drop implementation is still true @@ -83,14 +89,41 @@ impl ThreadKey { }) }) } + + /// Create a `ThreadKey` for the current thread, without checking to see if it + /// has already been acquired. + /// + /// This can be useful for `no_std` environments, where it's not possible to + /// check if the current thread has acquired a `ThreadKey` + /// + /// # Examples + /// + /// ``` + /// use happylock::ThreadKey; + /// + /// let key = ThreadKey::get().unwrap(); + /// ``` + /// + /// # Safety + /// + /// This is unsafe because it allows a thread to have multiple keys at a time. + /// Each thread must have no more than one `ThreadKey` at a time. + #[must_use] + pub const unsafe fn get_unchecked() -> Self { + Self { + phantom: PhantomData, + } + } } /// A dumb lock that's just a wrapper for an [`AtomicBool`]. #[derive(Default)] +#[cfg(feature = "std")] struct KeyCell { is_locked: Cell, } +#[cfg(feature = "std")] impl KeyCell { /// Attempt to lock the `KeyCell`. This is not a fair lock. #[must_use] @@ -107,14 +140,17 @@ impl KeyCell { #[cfg(test)] mod tests { + #[cfg(feature = "std")] use super::*; #[test] + #[cfg(feature = "std")] fn thread_key_returns_some_on_first_call() { assert!(ThreadKey::get().is_some()); } #[test] + #[cfg(feature = "std")] fn thread_key_returns_none_on_second_call() { let key = ThreadKey::get(); assert!(ThreadKey::get().is_none()); @@ -122,6 +158,7 @@ mod tests { } #[test] + #[cfg(feature = "std")] fn dropping_thread_key_allows_reobtaining() { drop(ThreadKey::get()); assert!(ThreadKey::get().is_some()) -- cgit v1.3.1