# wait-list This crate has been deprecated in favour of [`pin-list`](https://docs.rs/pin-list)! If you want to get the crate name for something else, please do not hesitate to [contact me] or email . [contact me]: https://sabrinajewson.org/ Original readme below: This crate provides `WaitList`, the most fundamental type for async synchronization. `WaitList` is implemented as an intrusive linked list of futures. ## Feature flags - `std`: Implements the `Lock` traits on locks from the standard library. - `lock_api_04`: Implements the `Lock` traits on locks from [`lock_api`] v0.4. This enables integration of crates like [`parking_lot`], [`spin`] and [`usync`]. - `loom_05`: Implements the `Lock` traits on locks from [`loom`] v0.5. ## Example A thread-safe unfair async mutex. ```rust use pin_project_lite::pin_project; use std::cell::UnsafeCell; use std::future::Future; use std::ops::Deref; use std::ops::DerefMut; use std::pin::Pin; use std::task; use std::task::Poll; use wait_list::WaitList; pub struct Mutex { data: UnsafeCell, waiters: WaitList, (), ()>, } unsafe impl Sync for Mutex {} impl Mutex { pub fn new(data: T) -> Self { Self { data: UnsafeCell::new(data), waiters: WaitList::new(std::sync::Mutex::new(false)), } } pub fn lock(&self) -> Lock<'_, T> { Lock { mutex: self, inner: wait_list::Wait::new(), } } } pin_project! { pub struct Lock<'mutex, T> { mutex: &'mutex Mutex, #[pin] inner: wait_list::Wait<'mutex, std::sync::Mutex, (), (), TryForward>, } } impl<'mutex, T> Future for Lock<'mutex, T> { type Output = Guard<'mutex, T>; fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll { let mut this = self.project(); let mut waiters = if this.inner.as_ref().is_completed() { // If we haven't initialized the future yet, lock the mutex for the first time this.mutex.waiters.lock_exclusive() } else { // Otherwise, wait for us to be woken match this.inner.as_mut().poll(cx) { Poll::Ready((waiters, ())) => waiters, Poll::Pending => return Poll::Pending, } }; // If the mutex is unlocked, mark it as locked and return the guard if !*waiters.guard { *waiters.guard = true; return Poll::Ready(Guard { mutex: this.mutex }); } // Otherwise, re-register ourselves to be woken when the mutex is unlocked again this.inner.init(cx.waker().clone(), &mut waiters, (), TryForward); Poll::Pending } } /// When the future is cancelled before the mutex guard can be taken, wake up the next waiter. struct TryForward; impl<'wait_list> wait_list::CancelCallback<'wait_list, std::sync::Mutex, (), ()> for TryForward { fn on_cancel( self, mut list: wait_list::LockedExclusive<'wait_list, std::sync::Mutex, (), ()>, output: (), ) { let _ = list.wake_one(()); } } pub struct Guard<'mutex, T> { mutex: &'mutex Mutex, } impl Deref for Guard<'_, T> { type Target = T; fn deref(&self) -> &Self::Target { unsafe { &*self.mutex.data.get() } } } impl DerefMut for Guard<'_, T> { fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *self.mutex.data.get() } } } impl Drop for Guard<'_, T> { fn drop(&mut self) { let mut waiters = self.mutex.waiters.lock_exclusive(); *waiters.guard = false; let _ = waiters.wake_one(()); } } # ``` [`lock_api`]: https://docs.rs/lock_api [`parking_lot`]: https://docs.rs/parking_lot [`spin`]: https://docs.rs/spin [`usync`]: https://docs.rs/usync [`loom`]: https://docs.rs/loom License: MIT