diff --git a/Cargo.toml b/Cargo.toml index 22f2805..c38b284 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2024" [features] default = ["alloc"] alloc = [] -std = [] +std = ["alloc"] nightly = [] [dependencies] diff --git a/src/drop_guard.rs b/src/drop_guard.rs index a708d32..4f00351 100644 --- a/src/drop_guard.rs +++ b/src/drop_guard.rs @@ -1,4 +1,8 @@ -use core::{cell::UnsafeCell, mem::ManuallyDrop}; +use core::{ + cell::UnsafeCell, + mem::ManuallyDrop, + ops::{Deref, DerefMut}, +}; /// A guard that runs a closure when it is dropped. pub struct DropGuard(UnsafeCell>); @@ -10,6 +14,10 @@ where pub fn new(f: F) -> DropGuard { Self(UnsafeCell::new(ManuallyDrop::new(f))) } + + pub fn guard(self, t: T) -> DropGuarded { + DropGuarded(t, self) + } } impl Drop for DropGuard @@ -32,3 +40,45 @@ where DropGuard::new(f) } } + +pub struct DropGuarded(T, DropGuard); + +impl DropGuarded +where + F: FnOnce(), +{ + pub fn new(value: T, f: F) -> Self { + Self(value, DropGuard::new(f)) + } + + pub fn into_inner(self) -> T { + self.0 + } + + pub fn map(self, f: G) -> DropGuarded + where + G: FnOnce(T) -> U, + { + DropGuarded(f(self.0), self.1) + } +} + +impl Deref for DropGuarded +where + F: FnOnce(), +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for DropGuarded +where + F: FnOnce(), +{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/src/sync.rs b/src/sync.rs index 19715e2..e1b90cc 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -46,6 +46,8 @@ impl Lock { } pub fn unlock(&self) { + // use release semantics to ensure that all previous writes are + // available to other threads. self.inner.fetch_and(!LOCKED_BIT, Ordering::Release); } @@ -115,6 +117,16 @@ impl Lock { state = self.inner.load(Ordering::Relaxed); } } + + pub fn wait(&self) { + let state = self.inner.load(Ordering::Acquire); + atomic_wait::wait(&self.inner, state); + } + + pub fn wake_one(&self) { + // Notify one thread waiting on this lock. + atomic_wait::wake_one(&self.inner); + } } pub struct SpinWait { diff --git a/src/util.rs b/src/util.rs index 0570972..c759785 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,8 @@ use core::ops::{Deref, DerefMut}; #[repr(transparent)] -pub struct Send(pub(self) T); +#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone, Copy)] +pub struct Send(pub T); unsafe impl core::marker::Send for Send {} @@ -22,6 +23,9 @@ impl Send { pub unsafe fn new(value: T) -> Self { Self(value) } + pub fn into_inner(self) -> T { + self.0 + } } /// returns the number of available hardware threads, or 1 if it cannot be determined.