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}