maniac_runtime/future/waker/
borrowed_waker.rs

1use core::task::Waker;
2
3use crate::future::waker::{DiatomicWaker, WaitUntil};
4
5/// A non-owned object that can await notifications from one or several
6/// [`WakeSourceRef`]s.
7///
8/// See the [crate-level documentation](crate) for usage.
9#[derive(Debug)]
10pub struct WakeSinkRef<'a> {
11    /// The shared data.
12    pub(crate) inner: &'a DiatomicWaker,
13}
14
15impl<'a> WakeSinkRef<'a> {
16    /// Creates a new `WakeSourceRef` associated to this sink with the same
17    /// lifetime.
18    #[inline]
19    pub fn source_ref(&self) -> WakeSourceRef<'a> {
20        WakeSourceRef { inner: self.inner }
21    }
22
23    /// Registers a new waker.
24    ///
25    /// Registration is lazy: the waker is cloned only if it differs from the
26    /// last registered waker (note that the last registered waker is cached
27    /// even if it was unregistered).
28    #[inline]
29    pub fn register(&mut self, waker: &Waker) {
30        // Safety: `DiatomicWaker::register`, `DiatomicWaker::unregister` and
31        // `DiatomicWaker::wait_until` cannot be used concurrently from multiple
32        // thread since `WakeSinkRef` does not implement `Clone` and the
33        // wrappers of the above methods require exclusive ownership to
34        // `WakeSinkRef`.
35        unsafe { self.inner.register(waker) };
36    }
37
38    /// Unregisters the waker.
39    ///
40    /// After the waker is unregistered, subsequent calls to
41    /// `WakeSourceRef::notify` will be ignored.
42    ///
43    /// Note that the previously-registered waker (if any) remains cached.
44    #[inline]
45    pub fn unregister(&mut self) {
46        // Safety: `DiatomicWaker::register`, `DiatomicWaker::unregister` and
47        // `DiatomicWaker::wait_until` cannot be used concurrently from multiple
48        // thread since `WakeSinkRef` does not implement `Clone` and the
49        // wrappers of the above methods require exclusive ownership to
50        // `WakeSinkRef`.
51        unsafe { self.inner.unregister() };
52    }
53
54    /// Returns a future that can be `await`ed until the provided predicate
55    /// returns a value.
56    ///
57    /// The predicate is checked each time a notification is received.
58    #[inline]
59    pub fn wait_until<P, T>(&mut self, predicate: P) -> WaitUntil<'_, P, T>
60    where
61        P: FnMut() -> Option<T>,
62    {
63        // Safety: `DiatomicWaker::register`, `DiatomicWaker::unregister` and
64        // `DiatomicWaker::wait_until` cannot be used concurrently from multiple
65        // thread since `WakeSinkRef` does not implement `Clone` and the
66        // wrappers of the above methods require exclusive ownership to
67        // `WakeSinkRef`.
68        unsafe { self.inner.wait_until(predicate) }
69    }
70}
71
72/// A non-owned object that can send notifications to a [`WakeSinkRef`].
73///
74/// See the [crate-level documentation](crate) for usage.
75#[derive(Clone, Debug)]
76pub struct WakeSourceRef<'a> {
77    /// The shared data.
78    pub(crate) inner: &'a DiatomicWaker,
79}
80
81impl WakeSourceRef<'_> {
82    /// Notifies the sink if a waker is registered.
83    ///
84    /// This automatically unregisters any waker that may have been previously
85    /// registered.
86    #[inline]
87    pub fn notify(&self) {
88        self.inner.notify();
89    }
90}