summaryrefslogtreecommitdiff
path: root/src/key.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/key.rs')
-rwxr-xr-xsrc/key.rs47
1 files changed, 42 insertions, 5 deletions
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<KeyCell> = LazyCell::new(KeyCell::default);
+ static KEY: std::cell::LazyCell<KeyCell> = 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<Self> {
// 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<bool>,
}
+#[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())