maitake_sync/
wait_map.rs

1//! A map of [`Waker`]s associated with keys, so that a task can be woken by
2//! key.
3//!
4//! See the documentation for the [`WaitMap`] type for details.
5use crate::{
6    blocking::{DefaultMutex, Mutex, ScopedRawMutex},
7    loom::{
8        cell::UnsafeCell,
9        sync::atomic::{AtomicUsize, Ordering::*},
10    },
11    util::{fmt, CachePadded, WakeBatch},
12};
13use cordyceps::{
14    list::{self, List},
15    Linked,
16};
17use core::{
18    fmt::Debug,
19    future::Future,
20    marker::PhantomPinned,
21    mem,
22    pin::Pin,
23    ptr::{self, NonNull},
24    task::{Context, Poll, Waker},
25};
26use mycelium_bitfield::{enum_from_bits, FromBits};
27use pin_project::{pin_project, pinned_drop};
28
29#[cfg(test)]
30mod tests;
31
32/// Errors returned by [`WaitMap::wait`], indicating a failed wake.
33#[derive(Copy, Clone, Debug, Eq, PartialEq)]
34#[non_exhaustive]
35pub enum WaitError {
36    /// The [`WaitMap`] has already been [closed].
37    ///
38    /// [closed]: WaitMap::close
39    Closed,
40
41    /// The received data has already been extracted
42    AlreadyConsumed,
43
44    /// The [`Wait`] was never added to the [`WaitMap`]
45    NeverAdded,
46
47    /// The [`WaitMap`] already had an item matching the given
48    /// key
49    Duplicate,
50}
51
52/// The result of a call to [`WaitMap::wait()`].
53pub type WaitResult<T> = Result<T, WaitError>;
54
55const fn closed<T>() -> Poll<WaitResult<T>> {
56    Poll::Ready(Err(WaitError::Closed))
57}
58
59const fn consumed<T>() -> Poll<WaitResult<T>> {
60    Poll::Ready(Err(WaitError::AlreadyConsumed))
61}
62
63const fn never_added<T>() -> Poll<WaitResult<T>> {
64    Poll::Ready(Err(WaitError::NeverAdded))
65}
66
67const fn duplicate<T>() -> Poll<WaitResult<T>> {
68    Poll::Ready(Err(WaitError::Duplicate))
69}
70
71const fn notified<T>(data: T) -> Poll<WaitResult<T>> {
72    Poll::Ready(Ok(data))
73}
74
75/// A map of [`Waker`]s associated with keys, allowing tasks to be woken by
76/// their key.
77///
78/// A `WaitMap` allows any number of tasks to [wait] asynchronously and be
79/// woken when a value with a certain key arrives. This can be used to
80/// implement structures like "async mailboxes", where an async function
81/// requests some data (such as a response) associated with a certain
82/// key (such as a message ID). When the data is received, the key can
83/// be used to provide the task with the desired data, as well as wake
84/// the task for further processing.
85///
86/// # Overriding the blocking mutex
87///
88/// This type uses a [blocking `Mutex`](crate::blocking::Mutex) internally to
89/// synchronize access to its wait list. By default, this is a [`DefaultMutex`]. To
90/// use an alternative [`ScopedRawMutex`] implementation, use the
91/// [`new_with_raw_mutex`](Self::new_with_raw_mutex) constructor. See [the documentation
92/// on overriding mutex
93/// implementations](crate::blocking#overriding-mutex-implementations) for more
94/// details.
95///
96/// # Examples
97///
98/// Waking a single task at a time by calling [`wake`][wake]:
99///
100/// ```ignore
101/// use std::sync::Arc;
102/// use maitake::scheduler;
103/// use maitake_sync::wait_map::{WaitMap, WakeOutcome};
104///
105/// const TASKS: usize = 10;
106///
107/// // In order to spawn tasks, we need a `Scheduler` instance.
108/// let scheduler = Scheduler::new();
109///
110/// // Construct a new `WaitMap`.
111/// let q = Arc::new(WaitMap::new());
112///
113/// // Spawn some tasks that will wait on the queue.
114/// // We'll use the task index (0..10) as the key.
115/// for i in 0..TASKS {
116///     let q = q.clone();
117///     scheduler.spawn(async move {
118///         let val = q.wait(i).await.unwrap();
119///         assert_eq!(val, i + 100);
120///     });
121/// }
122///
123/// // Tick the scheduler once.
124/// let tick = scheduler.tick();
125///
126/// // No tasks should complete on this tick, as they are all waiting
127/// // to be woken by the queue.
128/// assert_eq!(tick.completed, 0, "no tasks have been woken");
129///
130/// // We now wake each of the tasks, using the same key (0..10),
131/// // and provide them with a value that is their `key + 100`,
132/// // e.g. 100..110. Only the task that has been woken will be
133/// // notified.
134/// for i in 0..TASKS {
135///     let result = q.wake(&i, i + 100);
136///     assert!(matches!(result, WakeOutcome::Woke));
137///
138///     // Tick the scheduler.
139///     let tick = scheduler.tick();
140///
141///     // Exactly one task should have completed
142///     assert_eq!(tick.completed, 1);
143/// }
144///
145/// // Tick the scheduler.
146/// let tick = scheduler.tick();
147///
148/// // No additional tasks should be completed
149/// assert_eq!(tick.completed, 0);
150/// assert!(!tick.has_remaining);
151/// ```
152///
153/// # Implementation Notes
154///
155/// This type is currently implemented using [intrusive doubly-linked
156/// list][ilist].
157///
158/// The *[intrusive]* aspect of this map is important, as it means that it does
159/// not allocate memory. Instead, nodes in the linked list are stored in the
160/// futures of tasks trying to wait for capacity. This means that it is not
161/// necessary to allocate any heap memory for each task waiting to be woken.
162///
163/// However, the intrusive linked list introduces one new danger: because
164/// futures can be *cancelled*, and the linked list nodes live within the
165/// futures trying to wait on the queue, we *must* ensure that the node
166/// is unlinked from the list before dropping a cancelled future. Failure to do
167/// so would result in the list containing dangling pointers. Therefore, we must
168/// use a *doubly-linked* list, so that nodes can edit both the previous and
169/// next node when they have to remove themselves. This is kind of a bummer, as
170/// it means we can't use something nice like this [intrusive queue by Dmitry
171/// Vyukov][2], and there are not really practical designs for lock-free
172/// doubly-linked lists that don't rely on some kind of deferred reclamation
173/// scheme such as hazard pointers or QSBR.
174///
175/// Instead, we just stick a [`Mutex`] around the linked list, which must be
176/// acquired to pop nodes from it, or for nodes to remove themselves when
177/// futures are cancelled. This is a bit sad, but the critical sections for this
178/// mutex are short enough that we still get pretty good performance despite it.
179///
180/// [`Waker`]: core::task::Waker
181/// [wait]: WaitMap::wait
182/// [wake]: WaitMap::wake
183/// [`UnsafeCell`]: core::cell::UnsafeCell
184/// [ilist]: cordyceps::List
185/// [intrusive]: https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/fbl_containers_guide/introduction
186/// [2]: https://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue
187pub struct WaitMap<K: PartialEq, V, Lock: ScopedRawMutex = DefaultMutex> {
188    /// The wait queue's state variable.
189    state: CachePadded<AtomicUsize>,
190
191    /// The linked list of waiters.
192    ///
193    /// # Safety
194    ///
195    /// This is protected by a mutex; the mutex *must* be acquired when
196    /// manipulating the linked list, OR when manipulating waiter nodes that may
197    /// be linked into the list. If a node is known to not be linked, it is safe
198    /// to modify that node (such as by waking the stored [`Waker`]) without
199    /// holding the lock; otherwise, it may be modified through the list, so the
200    /// lock must be held when modifying the
201    /// node.
202    ///
203    /// A spinlock (from `mycelium_util`) is used here, in order to support
204    /// `no_std` platforms; when running `loom` tests, a `loom` mutex is used
205    /// instead to simulate the spinlock, because loom doesn't play nice with
206    /// real spinlocks.
207    queue: Mutex<List<Waiter<K, V>>, Lock>,
208}
209
210impl<K, V, Lock> Debug for WaitMap<K, V, Lock>
211where
212    K: PartialEq,
213    Lock: ScopedRawMutex,
214{
215    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
216        f.debug_struct("WaitMap")
217            .field("state", &self.state)
218            .field("queue", &self.queue)
219            .finish()
220    }
221}
222
223/// Future returned from [`WaitMap::wait()`].
224///
225/// This future is fused, so once it has completed, any future calls to poll
226/// will immediately return [`Poll::Ready`].
227///
228/// # Notes
229///
230/// This future is `!Unpin`, as it is unsafe to [`core::mem::forget`] a
231/// `Wait` future once it has been polled. For instance, the following code
232/// must not compile:
233///
234///```compile_fail
235/// use maitake_sync::wait_map::Wait;
236///
237/// // Calls to this function should only compile if `T` is `Unpin`.
238/// fn assert_unpin<T: Unpin>() {}
239///
240/// assert_unpin::<Wait<'_, usize, ()>>();
241/// ```
242#[derive(Debug)]
243#[pin_project(PinnedDrop)]
244#[must_use = "futures do nothing unless `.await`ed or `poll`ed"]
245pub struct Wait<'a, K: PartialEq, V, Lock: ScopedRawMutex = DefaultMutex> {
246    /// The [`WaitMap`] being waited on from.
247    queue: &'a WaitMap<K, V, Lock>,
248
249    /// Entry in the wait queue linked list.
250    #[pin]
251    waiter: Waiter<K, V>,
252}
253
254impl<'map, 'wait, K: PartialEq, V, Lock: ScopedRawMutex> Wait<'map, K, V, Lock> {
255    /// Returns a future that completes when the `Wait` item has been
256    /// added to the [`WaitMap`], and is ready to receive data
257    ///
258    /// This is useful for ensuring that a receiver is ready before
259    /// sending a message that will elicit the expected response.
260    ///
261    /// # Example
262    ///
263    /// ```ignore
264    /// use std::sync::Arc;
265    /// use maitake::scheduler;
266    /// use maitake_sync::wait_map::{WaitMap, WakeOutcome};
267    /// use futures_util::pin_mut;
268    ///
269    /// let scheduler = Scheduler::new();
270    /// let q = Arc::new(WaitMap::new());
271    ///
272    /// let q2 = q.clone();
273    /// scheduler.spawn(async move {
274    ///     let wait = q2.wait(0);
275    ///
276    ///     // At this point, we have created the future, but it has not yet
277    ///     // been added to the queue. We could immediately await 'wait',
278    ///     // but then we would be unable to progress further. We must
279    ///     // first pin the `wait` future, to ensure that it does not move
280    ///     // until it has been completed.
281    ///     pin_mut!(wait);
282    ///     wait.as_mut().subscribe().await.unwrap();
283    ///
284    ///     // We now know the waiter has been enqueued, at this point we could
285    ///     // send a message that will cause key == 0 to be returned, without
286    ///     // worrying about racing with the expected response, e.g:
287    ///     //
288    ///     // sender.send_with_id(0, SomeMessage).await?;
289    ///     //
290    ///     let val = wait.await.unwrap();
291    ///     assert_eq!(val, 10);
292    /// });
293    ///
294    /// assert!(matches!(q.wake(&0, 100), WakeOutcome::NoMatch(_)));
295    ///
296    /// let tick = scheduler.tick();
297    ///
298    /// assert!(matches!(q.wake(&0, 100), WakeOutcome::Woke));
299    /// ```
300    pub fn subscribe(self: Pin<&'wait mut Self>) -> Subscribe<'wait, 'map, K, V, Lock> {
301        Subscribe { wait: self }
302    }
303
304    /// Deprecated alias for [`Wait::subscribe`]. See that method for details.
305    #[deprecated(
306        since = "0.1.3",
307        note = "renamed to `subscribe` for consistency, use that instead"
308    )]
309    #[allow(deprecated)] // let us use the deprecated type alias
310    pub fn enqueue(self: Pin<&'wait mut Self>) -> EnqueueWait<'wait, 'map, K, V, Lock> {
311        self.subscribe()
312    }
313}
314
315/// A waiter node which may be linked into a wait queue.
316#[pin_project]
317struct Waiter<K: PartialEq, V> {
318    /// The intrusive linked list node.
319    #[pin]
320    node: UnsafeCell<Node<K, V>>,
321
322    /// The future's state.
323    state: WaitState,
324
325    key: K,
326}
327
328impl<K: PartialEq, V> Debug for Waiter<K, V> {
329    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
330        f.debug_struct("Waiter")
331            .field("node", &self.node)
332            .field("state", &self.state)
333            .field("key", &fmt::display(core::any::type_name::<K>()))
334            .field("val", &fmt::display(core::any::type_name::<V>()))
335            .finish()
336    }
337}
338
339#[repr(C)]
340struct Node<K: PartialEq, V> {
341    /// Intrusive linked list pointers.
342    ///
343    /// # Safety
344    ///
345    /// This *must* be the first field in the struct in order for the `Linked`
346    /// impl to be sound.
347    links: list::Links<Waiter<K, V>>,
348
349    /// The node's waker, if it has yet to be woken, or the data assigned to the
350    /// node, if it has been woken.
351    waker: Wakeup<V>,
352
353    // This type is !Unpin due to the heuristic from:
354    // <https://github.com/rust-lang/rust/pull/82834>
355    _pin: PhantomPinned,
356}
357
358impl<K: PartialEq, V> Debug for Node<K, V> {
359    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
360        f.debug_struct("Node")
361            .field("links", &self.links)
362            .field("waker", &self.waker)
363            .finish()
364    }
365}
366
367enum_from_bits! {
368    /// The state of a [`Waiter`] node in a [`WaitMap`].
369    #[derive(Debug, Eq, PartialEq)]
370    enum WaitState<u8> {
371        /// The waiter has not yet been enqueued.
372        ///
373        /// When in this state, the node is **not** part of the linked list, and
374        /// can be dropped without removing it from the list.
375        Start = 0b01,
376
377        /// The waiter is waiting.
378        ///
379        /// When in this state, the node **is** part of the linked list. If the
380        /// node is dropped in this state, it **must** be removed from the list
381        /// before dropping it. Failure to ensure this will result in dangling
382        /// pointers in the linked list!
383        Waiting = 0b10,
384
385        /// The waiter has been woken.
386        ///
387        /// When in this state, the node is **not** part of the linked list, and
388        /// can be dropped without removing it from the list.
389        Completed = 0b11,
390    }
391}
392
393/// The queue's current state.
394#[derive(Debug, Copy, Clone, Eq, PartialEq)]
395#[repr(u8)]
396enum State {
397    /// No waiters are queued, and there is no pending notification.
398    /// Waiting while the queue is in this state will enqueue the waiter
399    Empty = 0b00,
400
401    /// There are one or more waiters in the queue. Waiting while
402    /// the queue is in this state will not transition the state. Waking while
403    /// in this state will wake the appropriate waiter in the queue; if this empties
404    /// the queue, then the queue will transition to [`State::Empty`].
405    Waiting = 0b01,
406
407    // TODO(AJM): We have a state gap here. Is this okay?
408    /// The queue is closed. Waiting while in this state will return
409    /// [`Closed`] without transitioning the queue's state.
410    ///
411    /// *Note*: This *must* correspond to all state bits being set, as it's set
412    /// via a [`fetch_or`].
413    ///
414    /// [`Closed`]: crate::Closed
415    /// [`fetch_or`]: core::sync::atomic::AtomicUsize::fetch_or
416    Closed = 0b11,
417}
418
419#[derive(Clone)]
420enum Wakeup<V> {
421    /// The Waiter has been created, but no wake has occurred. This should
422    /// be the ONLY state while in `WaitState::Start`
423    Empty,
424
425    /// The Waiter has moved to the `WaitState::Waiting` state. We now
426    /// have the relevant waker, and are still waiting for data. This
427    /// corresponds to `WaitState::Waiting`.
428    Waiting(Waker),
429
430    /// The Waiter has received data, and is waiting for the woken task
431    /// to notice, and take the data by polling+completing the future.
432    /// This corresponds to `WaitState::Completed`.
433    ///
434    /// This state stores the received value; taking the value out of the waiter
435    /// advances the state to `Retrieved`.
436    DataReceived(V),
437
438    /// The waiter has received data, and already given it away, and has
439    /// no more data to give. This corresponds to `WaitState::Completed`.
440    Retreived,
441
442    /// The Queue the waiter is part of has been closed. No data will
443    /// be received from this future. This corresponds to
444    /// `WaitState::Completed`.
445    Closed,
446}
447
448// === impl WaitMap ===
449
450impl<K: PartialEq, V> WaitMap<K, V> {
451    loom_const_fn! {
452        /// Returns a new `WaitMap`.
453        ///
454        /// This constructor returns a `WaitMap` that uses a [`DefaultMutex`] as
455        /// the [`ScopedRawMutex`] implementation for wait list synchronization.
456        /// To use a different [`ScopedRawMutex`] implementation, use the
457        /// [`new_with_raw_mutex`](Self::new_with_raw_mutex) constructor, instead. See
458        /// [the documentation on overriding mutex
459        /// implementations](crate::blocking#overriding-mutex-implementations)
460        /// for more details.
461        #[must_use]
462        pub fn new() -> Self {
463            Self::new_with_raw_mutex(DefaultMutex::new())
464        }
465    }
466}
467
468impl<K, V, Lock> Default for WaitMap<K, V, Lock>
469where
470    K: PartialEq,
471    Lock: ScopedRawMutex + Default,
472{
473    fn default() -> Self {
474        Self::new_with_raw_mutex(Lock::default())
475    }
476}
477
478impl<K, V, Lock> WaitMap<K, V, Lock>
479where
480    K: PartialEq,
481    Lock: ScopedRawMutex,
482{
483    loom_const_fn! {
484        /// Returns a new `WaitMap`, using the provided [`ScopedRawMutex`]
485        /// implementation for wait-list synchronization.
486        ///
487        /// This constructor allows a `WaitMap` to be constructed with any type that
488        /// implements [`ScopedRawMutex`] as the underlying raw blocking mutex
489        /// implementation. See [the documentation on overriding mutex
490        /// implementations](crate::blocking#overriding-mutex-implementations)
491        /// for more details.
492        #[must_use]
493        pub fn new_with_raw_mutex(lock: Lock) -> Self {
494            Self {
495                state: CachePadded::new(AtomicUsize::new(State::Empty.into_usize())),
496                queue: Mutex::new_with_raw_mutex(List::new(), lock),
497            }
498        }
499    }
500}
501
502impl<K: PartialEq, V, Lock: ScopedRawMutex> WaitMap<K, V, Lock> {
503    /// Wake a certain task in the queue.
504    ///
505    /// If the queue is empty, a wakeup is stored in the `WaitMap`, and the
506    /// next call to [`wait`] will complete immediately.
507    ///
508    /// [`wait`]: WaitMap::wait
509    #[inline]
510    pub fn wake(&self, key: &K, val: V) -> WakeOutcome<V> {
511        // snapshot the queue's current state.
512        let mut state = self.load();
513
514        // check if any tasks are currently waiting on this queue. if there are
515        // no waiting tasks, store the wakeup to be consumed by the next call to
516        // `wait`.
517        match state {
518            // Something is waiting!
519            State::Waiting => {}
520
521            // if the queue is closed, bail.
522            State::Closed => return WakeOutcome::Closed(val),
523
524            // if the queue is empty, bail.
525            State::Empty => return WakeOutcome::NoMatch(val),
526        }
527
528        // okay, there are tasks waiting on the queue; we must acquire the lock
529        // on the linked list and wake the next task from the queue.
530        let mut val = Some(val);
531        let maybe_waker = self.queue.with_lock(|queue| {
532            test_debug!("wake: -> locked");
533
534            // the queue's state may have changed while we were waiting to acquire
535            // the lock, so we need to acquire a new snapshot.
536            state = self.load();
537
538            let node = self.node_match_locked(key, &mut *queue, state)?;
539            // if there's a node, give it the value and take the waker and
540            // return it. we return the waker from this closure rather than
541            // waking it, because we need to release the lock before waking the
542            // task.
543            let val = val
544                .take()
545                .expect("value is only taken elsewhere if there is no waker, but there is one");
546            let waker = Waiter::<K, V>::wake(node, &mut *queue, Wakeup::DataReceived(val));
547            Some(waker)
548        });
549
550        if let Some(waker) = maybe_waker {
551            waker.wake();
552            WakeOutcome::Woke
553        } else {
554            let val =
555                val.expect("value is only taken elsewhere if there is a waker, and there isn't");
556            WakeOutcome::NoMatch(val)
557        }
558    }
559
560    /// Returns `true` if this `WaitMap` is [closed](Self::close).
561    #[must_use]
562    pub fn is_closed(&self) -> bool {
563        self.load() == State::Closed
564    }
565
566    /// Close the queue, indicating that it may no longer be used.
567    ///
568    /// Once a queue is closed, all [`wait`] calls (current or future) will
569    /// return an error.
570    ///
571    /// This method is generally used when implementing higher-level
572    /// synchronization primitives or resources: when an event makes a resource
573    /// permanently unavailable, the queue can be closed.
574    ///
575    /// [`wait`]: Self::wait
576    pub fn close(&self) {
577        let state = self.state.fetch_or(State::Closed.into_usize(), SeqCst);
578        let state = test_dbg!(State::from_bits(state));
579        if state != State::Waiting {
580            return;
581        }
582
583        let mut batch = WakeBatch::new();
584        let mut waiters_remaining = true;
585        while waiters_remaining {
586            waiters_remaining = self.queue.with_lock(|waiters| {
587                while let Some(node) = waiters.pop_back() {
588                    let waker = Waiter::wake(node, waiters, Wakeup::Closed);
589                    if !batch.add_waker(waker) {
590                        // there's still room in the wake set, just keep adding to it.
591                        return true;
592                    }
593                }
594                false
595            });
596            batch.wake_all();
597        }
598    }
599
600    /// Wait to be woken up by this queue.
601    ///
602    /// This returns a [`Wait`] future that will complete when the task is
603    /// woken by a call to [`wake`] with a matching `key`, or when the `WaitMap`
604    /// is dropped.
605    ///
606    /// **Note**: `key`s must be unique. If the given key already exists in the
607    /// `WaitMap`, the future will resolve to an Error the first time it is polled
608    ///
609    /// [`wake`]: Self::wake
610    pub fn wait(&self, key: K) -> Wait<'_, K, V, Lock> {
611        Wait {
612            queue: self,
613            waiter: self.waiter(key),
614        }
615    }
616
617    /// Asynchronously poll the given function `f` until a condition occurs,
618    /// using the [`WaitMap`] to only re-poll when notified.
619    ///
620    /// This can be used to implement a "wait loop", turning a "try" function
621    /// (e.g. "try_recv" or "try_send") into an asynchronous function (e.g.
622    /// "recv" or "send").
623    ///
624    /// In particular, this function correctly *registers* interest in the [`WaitMap`]
625    /// prior to polling the function, ensuring that there is not a chance of a race
626    /// where the condition occurs AFTER checking but BEFORE registering interest
627    /// in the [`WaitMap`], which could lead to deadlock.
628    ///
629    /// This is intended to have similar behavior to `Condvar` in the standard library,
630    /// but asynchronous, and not requiring operating system intervention (or existence).
631    ///
632    /// In particular, this can be used in cases where interrupts or events are used
633    /// to signify readiness or completion of some task, such as the completion of a
634    /// DMA transfer, or reception of an ethernet frame. In cases like this, the interrupt
635    /// can wake the queue, allowing the polling function to check status fields for
636    /// partial progress or completion, and also return the status flags at the same time.
637    ///
638    /// Consider using [`Self::wait_for()`] if your function does not return a value.
639    ///
640    /// Consider using [`WaitMap::wait_for_value()`](super::wait_map::WaitMap::wait_for_value)
641    /// if you do not need multiple waiters.
642    ///
643    /// * [`Ok`]`(T)` if the closure returns [`Some`]`(T)`.
644    /// * [`Err`]`(`[`Closed`](crate::Closed)`)` if the [`WaitMap`] is closed.
645    ///
646    /// # Examples
647    ///
648    /// ```
649    /// # use tokio::task;
650    /// # #[tokio::main(flavor = "current_thread")]
651    /// # async fn test() {
652    /// use std::sync::Arc;
653    /// use maitake_sync::WaitMap;
654    /// use std::sync::atomic::{AtomicBool, Ordering};
655    ///
656    /// let map = Arc::new(WaitMap::new());
657    /// let wake1 = Arc::new(AtomicBool::new(false));
658    /// let wake2 = Arc::new(AtomicBool::new(false));
659    ///
660    /// let waiter1 = task::spawn({
661    ///     // clone items to move into the spawned task
662    ///     let map = map.clone();
663    ///     let wake = wake1.clone();
664    ///     async move {
665    ///         map.wait_for(1, || wake.load(Ordering::Relaxed)).await;
666    ///         println!("received wakeup 1!");
667    ///     }
668    /// });
669    ///
670    /// let waiter2 = task::spawn({
671    ///     // clone items to move into the spawned task
672    ///     let map = map.clone();
673    ///     let wake = wake2.clone();
674    ///     async move {
675    ///         map.wait_for(2, || wake.load(Ordering::Relaxed)).await;
676    ///         println!("received wakeup 2!");
677    ///     }
678    /// });
679    ///
680    /// println!("poking tasks without completion condition...");
681    ///
682    /// for i in 0..3 {
683    ///     map.wake(&i, ());
684    /// }
685    ///
686    /// // Let poll check the wake condition.
687    /// tokio::task::yield_now().await;
688    ///
689    /// assert!(!wake1.load(Ordering::Relaxed));
690    /// assert!(!wake2.load(Ordering::Relaxed));
691    /// wake1.store(true, Ordering::Relaxed);
692    /// wake2.store(true, Ordering::Relaxed);
693    ///
694    /// println!("poking tasks after completion condition...");
695    /// for i in 0..3 {
696    ///     map.wake(&i, ());
697    /// }
698    ///
699    /// waiter1.await.unwrap();
700    /// waiter2.await.unwrap();
701    /// # }
702    /// # test();
703    /// ```
704    pub async fn wait_for<F: FnMut() -> bool>(&self, key: K, mut f: F) -> WaitResult<()> {
705        let wait = self.wait(key);
706        let mut wait = core::pin::pin!(wait);
707
708        loop {
709            let _ = wait.as_mut().subscribe().await?;
710            if f() {
711                return Ok(());
712            }
713            wait.as_mut().await?;
714        }
715    }
716
717    /// Asynchronously poll the given function `f` until a condition occurs,
718    /// using the [`WaitMap`] to only re-poll when notified.
719    ///
720    /// This can be used to implement a "wait loop", turning a "try" function
721    /// (e.g. "try_recv" or "try_send") into an asynchronous function (e.g.
722    /// "recv" or "send").
723    ///
724    /// In particular, this function correctly *registers* interest in the [`WaitMap`]
725    /// prior to polling the function, ensuring that there is not a chance of a race
726    /// where the condition occurs AFTER checking but BEFORE registering interest
727    /// in the [`WaitMap`], which could lead to deadlock.
728    ///
729    /// This is intended to have similar behavior to `Condvar` in the standard library,
730    /// but asynchronous, and not requiring operating system intervention (or existence).
731    ///
732    /// In particular, this can be used in cases where interrupts or events are used
733    /// to signify readiness or completion of some task, such as the completion of a
734    /// DMA transfer, or reception of an ethernet frame. In cases like this, the interrupt
735    /// can wake the queue, allowing the polling function to check status fields for
736    /// partial progress or completion, and also return the status flags at the same time.
737    ///
738    /// Consider using [`Self::wait_for()`] if your function does not return a value.
739    ///
740    /// Consider using [`WaitMap::wait_for_value()`](super::wait_map::WaitMap::wait_for_value)
741    /// if you do not need multiple waiters.
742    ///
743    /// * [`Ok`]`(T)` if the closure returns [`Some`]`(T)`.
744    /// * [`Err`]`(`[`Closed`](crate::Closed)`)` if the [`WaitMap`] is closed.
745    ///
746    /// # Examples
747    ///
748    /// ```
749    /// # use tokio::task;
750    /// # #[tokio::main(flavor = "current_thread")]
751    /// # async fn test() {
752    /// use std::sync::Arc;
753    /// use maitake_sync::WaitMap;
754    /// use std::sync::atomic::{AtomicU8, Ordering};
755    ///
756    /// let map = Arc::new(WaitMap::new());
757    /// let num1 = Arc::new(AtomicU8::new(0));
758    /// let num2 = Arc::new(AtomicU8::new(0));
759    ///
760    /// let waiter1 = task::spawn({
761    ///     // clone items to move into the spawned task
762    ///     let map = map.clone();
763    ///     let num = num1.clone();
764    ///     async move {
765    ///         let rxd = map.wait_for_value(1, || {
766    ///             let val = num.load(Ordering::Relaxed);
767    ///             if val == 2 {
768    ///                 return Some(val);
769    ///             }
770    ///             None
771    ///         }).await.unwrap();
772    ///         assert_eq!(rxd, 2);
773    ///         println!("received wakeup with value: {rxd}");
774    ///     }
775    /// });
776    ///
777    /// let waiter2 = task::spawn({
778    ///     // clone items to move into the spawned task
779    ///     let map = map.clone();
780    ///     let num = num2.clone();
781    ///     async move {
782    ///         let rxd = map.wait_for_value(2, || {
783    ///             let val = num.load(Ordering::Relaxed);
784    ///             if val == 2 {
785    ///                 return Some(val);
786    ///             }
787    ///             None
788    ///         }).await.unwrap();
789    ///         assert_eq!(rxd, 2);
790    ///         println!("received wakeup with value: {rxd}");
791    ///     }
792    /// });
793    ///
794    /// println!("poking tasks without completion condition...");
795    ///
796    /// num1.fetch_add(1, Ordering::Relaxed);
797    /// map.wake(&1, ());
798    ///
799    /// num2.fetch_add(1, Ordering::Relaxed);
800    /// map.wake(&2, ());
801    ///
802    /// // Let poll check the wake condition.
803    /// tokio::task::yield_now().await;
804    ///
805    /// println!("poking tasks after completion condition...");
806    ///
807    /// num1.fetch_add(1, Ordering::Relaxed);
808    /// map.wake(&1, ());
809    ///
810    /// num2.fetch_add(1, Ordering::Relaxed);
811    /// map.wake(&2, ());
812    ///
813    /// waiter1.await.unwrap();
814    /// waiter2.await.unwrap();
815    /// # }
816    /// # test();
817    /// ```
818    pub async fn wait_for_value<T, F: FnMut() -> Option<T>>(&self, key: K, mut f: F) -> WaitResult<T> {
819        let wait = self.wait(key);
820        let mut wait = core::pin::pin!(wait);
821
822        loop {
823            let _ = wait.as_mut().subscribe().await?;
824            if let Some(t) = f() {
825                return Ok(t);
826            }
827            wait.as_mut().await?;
828        }
829    }
830
831    /// Returns a [`Waiter`] entry in this queue.
832    ///
833    /// This is factored out into a separate function because it's used by both
834    /// [`WaitMap::wait`] and [`WaitMap::wait_owned`].
835    fn waiter(&self, key: K) -> Waiter<K, V> {
836        let state = WaitState::Start;
837        Waiter {
838            state,
839            node: UnsafeCell::new(Node {
840                links: list::Links::new(),
841                waker: Wakeup::Empty,
842                _pin: PhantomPinned,
843            }),
844            key,
845        }
846    }
847
848    #[cfg_attr(test, track_caller)]
849    fn load(&self) -> State {
850        #[allow(clippy::let_and_return)]
851        let state = State::from_bits(self.state.load(SeqCst));
852        test_debug!("state.load() = {state:?}");
853        state
854    }
855
856    #[cfg_attr(test, track_caller)]
857    fn store(&self, state: State) {
858        test_debug!("state.store({state:?}");
859        self.state.store(state as usize, SeqCst);
860    }
861
862    #[cfg_attr(test, track_caller)]
863    fn compare_exchange(&self, current: State, new: State) -> Result<State, State> {
864        #[allow(clippy::let_and_return)]
865        let res = self
866            .state
867            .compare_exchange(current as usize, new as usize, SeqCst, SeqCst)
868            .map(State::from_bits)
869            .map_err(State::from_bits);
870        test_debug!("state.compare_exchange({current:?}, {new:?}) = {res:?}");
871        res
872    }
873
874    #[cold]
875    #[inline(never)]
876    fn node_match_locked(
877        &self,
878        key: &K,
879        queue: &mut List<Waiter<K, V>>,
880        curr: State,
881    ) -> Option<NonNull<Waiter<K, V>>> {
882        let state = curr;
883
884        // is the queue still in the `Waiting` state? it is possible that we
885        // transitioned to a different state while locking the queue.
886        if test_dbg!(state) != State::Waiting {
887            // If we are not waiting, we are either empty or closed.
888            // Not much to do.
889            return None;
890        }
891
892        let mut cursor = queue.cursor_front_mut();
893        let opt_node = cursor.remove_first(|t| &t.key == key);
894
895        // if we took the final waiter currently in the queue, transition to the
896        // `Empty` state.
897        if test_dbg!(queue.is_empty()) {
898            self.store(State::Empty);
899        }
900
901        opt_node
902    }
903}
904
905/// The result of an attempted [`WaitMap::wake()`] operation.
906#[derive(Debug)]
907pub enum WakeOutcome<V> {
908    /// The task was successfully woken, and the data was provided.
909    Woke,
910
911    /// No task matching the given key was found in the queue.
912    NoMatch(V),
913
914    /// The queue was already closed when the wake was attempted,
915    /// and the data was not provided to any task.
916    Closed(V),
917}
918
919// === impl WaitError ===
920
921impl fmt::Display for WaitError {
922    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
923        match self {
924            Self::Closed => f.pad("WaitMap closed"),
925            Self::Duplicate => f.pad("duplicate key"),
926            &Self::AlreadyConsumed => f.pad("received data has already been consumed"),
927            Self::NeverAdded => f.pad("Wait was never added to WaitMap"),
928        }
929    }
930}
931
932feature! {
933    #![feature = "core-error"]
934    impl core::error::Error for WaitError {}
935}
936
937// === impl Waiter ===
938
939/// A future that ensures a [`Wait`] has been added to a [`WaitMap`].
940///
941/// See [`Wait::subscribe`] for more information and usage example.
942#[must_use = "futures do nothing unless `.await`ed or `poll`ed"]
943#[derive(Debug)]
944pub struct Subscribe<'a, 'b, K, V, Lock = DefaultMutex>
945where
946    K: PartialEq,
947    Lock: ScopedRawMutex,
948{
949    wait: Pin<&'a mut Wait<'b, K, V, Lock>>,
950}
951
952impl<K, V, Lock> Future for Subscribe<'_, '_, K, V, Lock>
953where
954    K: PartialEq,
955    Lock: ScopedRawMutex,
956{
957    type Output = WaitResult<()>;
958
959    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
960        let this = self.wait.as_mut().project();
961        if let WaitState::Start = test_dbg!(&this.waiter.state) {
962            this.waiter.start_to_wait(this.queue, cx)
963        } else {
964            Poll::Ready(Ok(()))
965        }
966    }
967}
968
969/// Deprecated alias for [`Subscribe`]. See the [`Wait::subscribe`]
970/// documentation for more details.
971#[deprecated(
972    since = "0.1.3",
973    note = "renamed to `Subscribe` for consistency, use that instead"
974)]
975pub type EnqueueWait<'a, 'b, K, V, Lock> = Subscribe<'a, 'b, K, V, Lock>;
976
977impl<K: PartialEq, V> Waiter<K, V> {
978    /// Wake the task that owns this `Waiter`.
979    ///
980    /// # Safety
981    ///
982    /// This is only safe to call while the list is locked. The `list`
983    /// parameter ensures this method is only called while holding the lock, so
984    /// this can be safe.
985    ///
986    /// Of course, that must be the *same* list that this waiter is a member of,
987    /// and currently, there is no way to ensure that...
988    #[inline(always)]
989    #[cfg_attr(loom, track_caller)]
990    fn wake(this: NonNull<Self>, list: &mut List<Self>, wakeup: Wakeup<V>) -> Waker {
991        Waiter::with_node(this, list, |node| {
992            let waker = test_dbg!(mem::replace(&mut node.waker, wakeup));
993            match waker {
994                Wakeup::Waiting(waker) => waker,
995                _ => unreachable!("tried to wake a waiter in the {:?} state!", waker),
996            }
997        })
998    }
999
1000    /// # Safety
1001    ///
1002    /// This is only safe to call while the list is locked. The dummy `_list`
1003    /// parameter ensures this method is only called while holding the lock, so
1004    /// this can be safe.
1005    ///
1006    /// Of course, that must be the *same* list that this waiter is a member of,
1007    /// and currently, there is no way to ensure that...
1008    #[inline(always)]
1009    #[cfg_attr(loom, track_caller)]
1010    fn with_node<T>(
1011        mut this: NonNull<Self>,
1012        _list: &mut List<Self>,
1013        f: impl FnOnce(&mut Node<K, V>) -> T,
1014    ) -> T {
1015        unsafe {
1016            // safety: this is only called while holding the lock on the queue,
1017            // so it's safe to mutate the waiter.
1018            this.as_mut().node.with_mut(|node| f(&mut *node))
1019        }
1020    }
1021
1022    /// Moves a `Wait` from the `Start` condition.
1023    ///
1024    /// Caller MUST ensure the `Wait` is in the start condition before calling.
1025    fn start_to_wait<Lock>(
1026        mut self: Pin<&mut Self>,
1027        queue: &WaitMap<K, V, Lock>,
1028        cx: &mut Context<'_>,
1029    ) -> Poll<WaitResult<()>>
1030    where
1031        Lock: ScopedRawMutex,
1032    {
1033        // Try to wait...
1034        test_debug!("poll_wait: locking...");
1035        queue.queue.with_lock(move |waiters| {
1036            test_debug!("poll_wait: -> locked");
1037            let mut this = self.as_mut().project();
1038
1039            debug_assert!(
1040                matches!(this.state, WaitState::Start),
1041                "start_to_wait should ONLY be called from the Start state!"
1042            );
1043
1044            let mut queue_state = queue.load();
1045
1046            // transition the queue to the waiting state
1047            'to_waiting: loop {
1048                match test_dbg!(queue_state) {
1049                    // the queue is `Empty`, transition to `Waiting`
1050                    State::Empty => match queue.compare_exchange(queue_state, State::Waiting) {
1051                        Ok(_) => break 'to_waiting,
1052                        Err(actual) => queue_state = actual,
1053                    },
1054                    // the queue is already `Waiting`
1055                    State::Waiting => break 'to_waiting,
1056                    State::Closed => return closed(),
1057                }
1058            }
1059
1060            // Check if key already exists
1061            //
1062            // Note: It's okay not to re-update the state here, if we were empty
1063            // this check will never trigger, if we are already waiting, we should
1064            // still be waiting.
1065            let mut cursor = waiters.cursor_front_mut();
1066            if cursor.any(|n| &n.key == this.key) {
1067                return duplicate();
1068            }
1069
1070            // enqueue the node
1071            *this.state = WaitState::Waiting;
1072            this.node.as_mut().with_mut(|node| {
1073                unsafe {
1074                    // safety: we may mutate the node because we are
1075                    // holding the lock.
1076                    (*node).waker = Wakeup::Waiting(cx.waker().clone());
1077                }
1078            });
1079            let ptr = unsafe { NonNull::from(Pin::into_inner_unchecked(self)) };
1080            waiters.push_front(ptr);
1081
1082            Poll::Ready(Ok(()))
1083        })
1084    }
1085
1086    fn poll_wait<Lock>(
1087        mut self: Pin<&mut Self>,
1088        queue: &WaitMap<K, V, Lock>,
1089        cx: &mut Context<'_>,
1090    ) -> Poll<WaitResult<V>>
1091    where
1092        Lock: ScopedRawMutex,
1093    {
1094        test_debug!(ptr = ?fmt::ptr(self.as_mut()), "Waiter::poll_wait");
1095        let this = self.as_mut().project();
1096
1097        match test_dbg!(&this.state) {
1098            WaitState::Start => {
1099                let _ = self.start_to_wait(queue, cx)?;
1100                Poll::Pending
1101            }
1102            WaitState::Waiting => {
1103                // We must lock the linked list in order to safely mutate our node in
1104                // the list. We don't actually need the mutable reference to the
1105                // queue here, though.
1106                queue.queue.with_lock(|_waiters| {
1107                    this.node.with_mut(|node| unsafe {
1108                        // safety: we may mutate the node because we are
1109                        // holding the lock.
1110                        let node = &mut *node;
1111                        let result;
1112                        node.waker = match mem::replace(&mut node.waker, Wakeup::Empty) {
1113                            // We already had a waker, but are now getting another one.
1114                            // Store the new one, droping the old one
1115                            Wakeup::Waiting(waker) => {
1116                                result = Poll::Pending;
1117                                if !waker.will_wake(cx.waker()) {
1118                                    Wakeup::Waiting(cx.waker().clone())
1119                                } else {
1120                                    Wakeup::Waiting(waker)
1121                                }
1122                            }
1123                            // We have received the data, take the data out of the
1124                            // future, and provide it to the poller
1125                            Wakeup::DataReceived(val) => {
1126                                result = notified(val);
1127                                Wakeup::Retreived
1128                            }
1129                            Wakeup::Retreived => {
1130                                result = consumed();
1131                                Wakeup::Retreived
1132                            }
1133
1134                            Wakeup::Closed => {
1135                                *this.state = WaitState::Completed;
1136                                result = closed();
1137                                Wakeup::Closed
1138                            }
1139                            Wakeup::Empty => {
1140                                result = never_added();
1141                                Wakeup::Closed
1142                            }
1143                        };
1144                        result
1145                    })
1146                })
1147            }
1148            WaitState::Completed => consumed(),
1149        }
1150    }
1151
1152    /// Release this `Waiter` from the queue.
1153    ///
1154    /// This is called from the `drop` implementation for the [`Wait`] and
1155    /// [`WaitOwned`] futures.
1156    fn release<Lock>(mut self: Pin<&mut Self>, queue: &WaitMap<K, V, Lock>)
1157    where
1158        Lock: ScopedRawMutex,
1159    {
1160        let state = *(self.as_mut().project().state);
1161        let ptr = NonNull::from(unsafe { Pin::into_inner_unchecked(self) });
1162        test_debug!(self = ?fmt::ptr(ptr), ?state, ?queue, "Waiter::release");
1163
1164        // if we're not enqueued, we don't have to do anything else.
1165        if state != WaitState::Waiting {
1166            return;
1167        }
1168
1169        queue.queue.with_lock(|waiters| {
1170            let state = queue.load();
1171
1172            // remove the node
1173            unsafe {
1174                // safety: we have the lock on the queue, so this is safe.
1175                waiters.remove(ptr);
1176            };
1177
1178            // if we removed the last waiter from the queue, transition the state to
1179            // `Empty`.
1180            if test_dbg!(waiters.is_empty()) && state == State::Waiting {
1181                queue.store(State::Empty);
1182            }
1183        })
1184    }
1185}
1186
1187unsafe impl<K: PartialEq, V> Linked<list::Links<Waiter<K, V>>> for Waiter<K, V> {
1188    type Handle = NonNull<Waiter<K, V>>;
1189
1190    fn into_ptr(r: Self::Handle) -> NonNull<Self> {
1191        r
1192    }
1193
1194    unsafe fn from_ptr(ptr: NonNull<Self>) -> Self::Handle {
1195        ptr
1196    }
1197
1198    unsafe fn links(target: NonNull<Self>) -> NonNull<list::Links<Waiter<K, V>>> {
1199        // Safety: using `ptr::addr_of!` avoids creating a temporary
1200        // reference, which stacked borrows dislikes.
1201        let node = ptr::addr_of!((*target.as_ptr()).node);
1202        (*node).with_mut(|node| {
1203            let links = ptr::addr_of_mut!((*node).links);
1204            // Safety: since the `target` pointer is `NonNull`, we can assume
1205            // that pointers to its members are also not null, making this use
1206            // of `new_unchecked` fine.
1207            NonNull::new_unchecked(links)
1208        })
1209    }
1210}
1211
1212// === impl Wait ===
1213
1214impl<K, V, Lock> Future for Wait<'_, K, V, Lock>
1215where
1216    K: PartialEq,
1217    Lock: ScopedRawMutex,
1218{
1219    type Output = WaitResult<V>;
1220
1221    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1222        let this = self.project();
1223        this.waiter.poll_wait(this.queue, cx)
1224    }
1225}
1226
1227#[pinned_drop]
1228impl<K, V, Lock> PinnedDrop for Wait<'_, K, V, Lock>
1229where
1230    K: PartialEq,
1231    Lock: ScopedRawMutex,
1232{
1233    fn drop(mut self: Pin<&mut Self>) {
1234        let this = self.project();
1235        this.waiter.release(this.queue);
1236    }
1237}
1238
1239// === impl MapState ===
1240
1241impl State {
1242    #[inline]
1243    fn from_bits(bits: usize) -> Self {
1244        Self::try_from_bits(bits).expect("This shouldn't be possible")
1245    }
1246}
1247
1248impl FromBits<usize> for State {
1249    const BITS: u32 = 2;
1250    type Error = core::convert::Infallible;
1251
1252    fn try_from_bits(bits: usize) -> Result<Self, Self::Error> {
1253        Ok(match bits as u8 {
1254            bits if bits == Self::Empty as u8 => Self::Empty,
1255            bits if bits == Self::Waiting as u8 => Self::Waiting,
1256            bits if bits == Self::Closed as u8 => Self::Closed,
1257            _ => unsafe {
1258                // TODO(AJM): this isn't *totally* true anymore...
1259                unreachable_unchecked!("all potential 2-bit patterns should be covered!")
1260            },
1261        })
1262    }
1263
1264    fn into_bits(self) -> usize {
1265        self.into_usize()
1266    }
1267}
1268
1269impl State {
1270    const fn into_usize(self) -> usize {
1271        self as u8 as usize
1272    }
1273}
1274
1275// === impl WaitOwned ===
1276
1277feature! {
1278    #![feature = "alloc"]
1279
1280    use alloc::sync::Arc;
1281
1282    /// Future returned from [`WaitMap::wait_owned()`].
1283    ///
1284    /// This is identical to the [`Wait`] future, except that it takes an
1285    /// [`Arc`] reference to the [`WaitMap`], allowing the returned future to
1286    /// live for the `'static` lifetime.
1287    ///
1288    /// This future is fused, so once it has completed, any future calls to poll
1289    /// will immediately return [`Poll::Ready`].
1290    ///
1291    /// # Notes
1292    ///
1293    /// This future is `!Unpin`, as it is unsafe to [`core::mem::forget`] a
1294    /// `Wait` future once it has been polled. For instance, the following code
1295    /// must not compile:
1296    ///
1297    ///```compile_fail
1298    /// use maitake_sync::wait_map::WaitOwned;
1299    ///
1300    /// // Calls to this function should only compile if `T` is `Unpin`.
1301    /// fn assert_unpin<T: Unpin>() {}
1302    ///
1303    /// assert_unpin::<WaitOwned<'_, usize, ()>>();
1304    #[derive(Debug)]
1305    #[pin_project(PinnedDrop)]
1306    pub struct WaitOwned<K: PartialEq, V, Lock: ScopedRawMutex = DefaultMutex> {
1307        /// The `WaitMap` being waited on.
1308        queue: Arc<WaitMap<K, V, Lock>>,
1309
1310        /// Entry in the wait queue.
1311        #[pin]
1312        waiter: Waiter<K, V>,
1313    }
1314
1315    impl<K: PartialEq, V, Lock: ScopedRawMutex> WaitMap<K, V, Lock> {
1316        /// Wait to be woken up by this queue, returning a future that's valid
1317        /// for the `'static` lifetime.
1318        ///
1319        /// This is identical to the [`wait`] method, except that it takes a
1320        /// [`Arc`] reference to the [`WaitMap`], allowing the returned future to
1321        /// live for the `'static` lifetime.
1322        ///
1323        /// This returns a [`WaitOwned`] future that will complete when the task is
1324        /// woken by a call to [`wake`] with a matching `key`, or when the `WaitMap`
1325        /// is dropped.
1326        ///
1327        /// **Note**: `key`s must be unique. If the given key already exists in the
1328        /// `WaitMap`, the future will resolve to an Error the first time it is polled
1329        ///
1330        /// [`wake`]: Self::wake
1331        /// [`wait`]: Self::wait
1332        pub fn wait_owned(self: &Arc<Self>, key: K) -> WaitOwned<K, V, Lock> {
1333            let waiter = self.waiter(key);
1334            let queue = self.clone();
1335            WaitOwned { queue, waiter }
1336        }
1337    }
1338
1339    impl<K: PartialEq, V, Lock: ScopedRawMutex> Future for WaitOwned<K, V, Lock> {
1340        type Output = WaitResult<V>;
1341
1342        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1343            let this = self.project();
1344            this.waiter.poll_wait(&*this.queue, cx)
1345        }
1346    }
1347
1348    #[pinned_drop]
1349    impl<K, V, Lock> PinnedDrop for WaitOwned<K, V, Lock>
1350    where
1351        K: PartialEq,
1352        Lock: ScopedRawMutex,
1353    {
1354        fn drop(mut self: Pin<&mut Self>) {
1355            let this = self.project();
1356            this.waiter.release(&*this.queue);
1357        }
1358    }
1359}
1360
1361impl<V> fmt::Debug for Wakeup<V> {
1362    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1363        match self {
1364            Self::Empty => f.write_str("Wakeup::Empty"),
1365            Self::Waiting(waker) => f.debug_tuple("Wakeup::Waiting").field(waker).finish(),
1366            Self::DataReceived(_) => f.write_str("Wakeup::DataReceived(..)"),
1367            Self::Retreived => f.write_str("Wakeup::Retrieved"),
1368            Self::Closed => f.write_str("Wakeup::Closed"),
1369        }
1370    }
1371}