Skip to main content

nuclei/sync/
notify.rs

1//! Task notification: wake one waiter, or every waiter, without a value.
2
3#![allow(unsafe_code)]
4
5use core::fmt;
6use core::future::Future;
7use core::pin::Pin;
8use core::task::{Context, Poll, Waker};
9use std::sync::Arc;
10
11use super::internal::{AtomicUsize, Ordering, UnsafeCell};
12use super::list::List;
13use super::queue::{Arrivals, FIRST_BIT, Policy, QUEUED, Step, WaitQueue};
14use super::waiter::{Cancel, Wait, WakeList, release_queued};
15
16/// A `notify_one` or `notify_last` found nobody waiting and left this for
17/// the next waiter.
18const PERMIT: usize = 1 << FIRST_BIT;
19
20/// The payload a drainer leaves on a waiter it granted for `notify_one`,
21/// so a waiter dropped before it saw the grant passes it on. Waiters
22/// otherwise carry their generation, which never reaches this value.
23const BY_FIRST: usize = usize::MAX;
24
25/// The same for `notify_last`, which the dropped waiter passes on as a
26/// `notify_last`.
27const BY_LAST: usize = usize::MAX - 1;
28
29/// Wakes tasks waiting for an event that carries no value.
30///
31/// [`notify_one`](Self::notify_one) wakes the oldest waiter, or, when
32/// nobody waits, stores one permit that the next
33/// [`notified`](Self::notified) consumes at once, so a notification sent
34/// just before the wait is not lost. [`notify_last`](Self::notify_last) is
35/// the same for the newest waiter.
36/// [`notify_waiters`](Self::notify_waiters) wakes every waiter that exists
37/// when it is called and stores nothing.
38///
39/// A [`Notified`] future receives `notify_waiters` calls made any time
40/// after it was created, even before it is first polled. It receives
41/// `notify_one` and `notify_last` only once it is polled or
42/// [enabled](Notified::enable).
43///
44/// ```
45/// use nuclei::sync::Notify;
46/// use std::future::Future;
47/// use std::pin::pin;
48/// use std::task::{Context, Poll, Waker};
49///
50/// let notify = Notify::new();
51/// notify.notify_one();
52/// let mut cx = Context::from_waker(Waker::noop());
53/// let waiting = pin!(notify.notified());
54/// assert!(waiting.poll(&mut cx).is_ready(), "the stored permit is consumed");
55/// ```
56pub struct Notify {
57    queue: WaitQueue,
58    waiting: UnsafeCell<List>,
59    /// `notify_one` calls a drain pass has yet to serve.
60    pending_first: AtomicUsize,
61    /// `notify_last` calls a drain pass has yet to serve.
62    pending_last: AtomicUsize,
63    /// How many `notify_waiters` calls there have been.
64    generation: AtomicUsize,
65}
66
67// SAFETY: the waiting list is touched only by the drain role's holder.
68unsafe impl Send for Notify {}
69// SAFETY: as above.
70unsafe impl Sync for Notify {}
71
72impl Notify {
73    loom_const_fn! {
74        /// A `Notify` with nobody waiting and no stored permit.
75        pub fn new() -> Self {
76            Self {
77                queue: WaitQueue::new(0),
78                waiting: UnsafeCell::new(List::new()),
79                pending_first: AtomicUsize::new(0),
80                pending_last: AtomicUsize::new(0),
81                generation: AtomicUsize::new(0),
82            }
83        }
84    }
85
86    loom_const_fn! {
87        /// A `Notify` with nobody waiting and no stored permit, usable in a
88        /// `static`.
89        pub fn const_new() -> Self {
90            Self::new()
91        }
92    }
93
94    /// A future that completes on the next notification.
95    ///
96    /// It is guaranteed to receive `notify_waiters` calls from the moment it
97    /// is created, polled or not. It receives `notify_one` and `notify_last`
98    /// from its first poll, or its first call to
99    /// [`enable`](Notified::enable).
100    pub fn notified(&self) -> Notified<'_> {
101        Notified {
102            notify: self,
103            core: Core::new(self),
104        }
105    }
106
107    /// [`notified`](Self::notified) through an `Arc`, so the future can
108    /// outlive the borrow and move between tasks.
109    pub fn notified_owned(self: Arc<Self>) -> OwnedNotified {
110        OwnedNotified {
111            core: Core::new(&self),
112            notify: self,
113        }
114    }
115
116    /// Wakes the oldest waiter, or stores a permit when nobody waits. At
117    /// most one permit is stored.
118    pub fn notify_one(&self) {
119        self.notify_with(&self.pending_first);
120    }
121
122    /// Wakes the newest waiter, or stores a permit when nobody waits: as
123    /// [`notify_one`](Self::notify_one), but for the waiter that queued last
124    /// instead of the one that queued first.
125    pub fn notify_last(&self) {
126        self.notify_with(&self.pending_last);
127    }
128
129    /// One owed wake of `strategy`, or a stored permit if nobody is queued.
130    fn notify_with(&self, owed: &AtomicUsize) {
131        let before = self.transition(|state| {
132            if state & QUEUED != 0 {
133                Step::Keep
134            } else {
135                Step::Set(state | PERMIT)
136            }
137        });
138        if before & QUEUED == 0 {
139            return;
140        }
141        owed.fetch_add(1, Ordering::Release);
142        self.transition(Step::Drain);
143    }
144
145    /// Wakes every task waiting now: every [`Notified`] created before this
146    /// call, whether or not it has been polled. Stores no permit.
147    pub fn notify_waiters(&self) {
148        self.generation.fetch_add(1, Ordering::Release);
149        // A read-modify-write even with nobody queued: a waiter that queues
150        // concurrently either is seen here or, through the state word,
151        // sees the new generation in its own pass.
152        self.transition(|state| {
153            if state & QUEUED != 0 {
154                Step::Drain(state)
155            } else {
156                Step::Set(state)
157            }
158        });
159    }
160
161    /// Takes a stored permit if nobody is queued ahead.
162    fn take_permit(&self) -> bool {
163        let before = self.transition(|state| {
164            if state & (QUEUED | PERMIT) == PERMIT {
165                Step::Set(state & !PERMIT)
166            } else {
167                Step::Keep
168            }
169        });
170        before & (QUEUED | PERMIT) == PERMIT
171    }
172
173    /// The current generation. The top bit is masked off so it never
174    /// equals [`BY_FIRST`]. Generations are compared, never ordered: a
175    /// waiter could miss one only if 2^(usize::BITS - 1) `notify_waiters`
176    /// calls passed while one drain pass stood still.
177    fn generation(&self) -> usize {
178        self.generation.load(Ordering::Acquire) & (usize::MAX >> 1)
179    }
180}
181
182impl Policy for Notify {
183    fn queue(&self) -> &WaitQueue {
184        &self.queue
185    }
186
187    fn pass(&self, arrivals: Arrivals, woken: &mut WakeList<'_>, _wake_front: bool) -> usize {
188        let pool = &self.queue;
189        // Read after the arrivals were taken, so each arrival carries this
190        // generation or an older one.
191        let generation = self.generation();
192        // SAFETY: only the drain role's holder runs a pass.
193        self.waiting.with_mut(|waiting| unsafe {
194            let waiting = &mut *waiting;
195            // Every node a pass leaves queued carries the generation that
196            // pass read, so the queued nodes are all of one generation:
197            // a `notify_waiters` since then expired every one of them, and
198            // granting from the front reaches them all.
199            while let Some(node) = waiting.front(pool) {
200                if node.as_ref().payload() == generation {
201                    break;
202                }
203                waiting.pop_front();
204                woken.grant(node);
205            }
206            // Generation order is not queue order: a waiter can pass its
207            // check, stop before it queues, and queue after a newer one.
208            // So each arrival is checked on its own, and only the current
209            // generation is queued, which keeps the rule above.
210            for node in arrivals {
211                if node.as_ref().is_cancelled() {
212                    release_queued(node, pool);
213                } else if node.as_ref().payload() != generation {
214                    woken.grant(node);
215                } else {
216                    waiting.push_back(node);
217                }
218            }
219            waiting.tidy(&self.queue);
220            let mut first = self.pending_first.swap(0, Ordering::AcqRel);
221            let mut last = self.pending_last.swap(0, Ordering::AcqRel);
222            if waiting.front(pool).is_some()
223                && self.queue.state.fetch_and(!PERMIT, Ordering::AcqRel) & PERMIT != 0
224            {
225                first += 1;
226            }
227            while first > 0 {
228                let Some(node) = waiting.front(pool) else {
229                    break;
230                };
231                waiting.pop_front();
232                node.as_ref().set_payload(BY_FIRST);
233                if woken.grant(node) {
234                    first -= 1;
235                }
236            }
237            while last > 0 {
238                let Some(node) = waiting.back(pool) else {
239                    break;
240                };
241                waiting.pop_back();
242                node.as_ref().set_payload(BY_LAST);
243                if woken.grant(node) {
244                    last -= 1;
245                }
246            }
247            if first + last > 0 {
248                self.queue.state.fetch_or(PERMIT, Ordering::AcqRel);
249            }
250            if waiting.is_empty() { QUEUED } else { 0 }
251        })
252    }
253}
254
255impl Drop for Notify {
256    fn drop(&mut self) {
257        let pool = &self.queue;
258        // SAFETY: `&mut self` rules out a concurrent pass.
259        self.waiting
260            .with_mut(|waiting| unsafe { (*waiting).clear(pool) });
261    }
262}
263
264impl Default for Notify {
265    fn default() -> Self {
266        Self::new()
267    }
268}
269
270impl fmt::Debug for Notify {
271    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272        f.debug_struct("Notify").finish_non_exhaustive()
273    }
274}
275
276/// What [`Notified`] and [`OwnedNotified`] share: the generation of the
277/// `notify_waiters` count when the future was made, its place in the queue
278/// and whether it completed.
279struct Core {
280    generation: usize,
281    wait: Wait,
282    done: bool,
283}
284
285impl Core {
286    fn new(notify: &Notify) -> Self {
287        Self {
288            generation: notify.generation(),
289            wait: Wait::new(),
290            done: false,
291        }
292    }
293
294    /// Looks for a notification, queueing on `notify` if there is none yet.
295    /// With `waker`, registers it; without one (an `enable`), the wait is
296    /// queued with a waker that does nothing, which the first poll replaces.
297    /// True once the notification is here.
298    fn drive(&mut self, notify: &Notify, waker: Option<&Waker>) -> bool {
299        if self.done {
300            return true;
301        }
302        let ready = if self.wait.is_queued() {
303            match waker {
304                Some(waker) => self.wait.poll(&notify.queue, Some(waker)).is_ready(),
305                // An `enable` has no waker to register: it only looks.
306                None => self.wait.granted(&notify.queue).is_some(),
307            }
308        } else if notify.generation() != self.generation || notify.take_permit() {
309            true
310        } else {
311            notify.enqueue(
312                &mut self.wait,
313                self.generation,
314                waker.unwrap_or(Waker::noop()),
315            );
316            self.wait.poll(&notify.queue, None).is_ready()
317        };
318        self.done = ready;
319        ready
320    }
321
322    /// Leaves the queue; a `notify_one` or `notify_last` that reached the
323    /// wait unseen goes to the next waiter.
324    fn cancel(&mut self, notify: &Notify) {
325        match self.wait.cancel(&notify.queue) {
326            Cancel::Idle => {}
327            Cancel::Withdrawn(_) => notify.withdrawn(false),
328            Cancel::Granted(BY_FIRST) => notify.notify_one(),
329            Cancel::Granted(BY_LAST) => notify.notify_last(),
330            Cancel::Granted(_) => {}
331        }
332    }
333}
334
335/// The future [`Notify::notified`] returns.
336///
337/// It is fused: once it completes, polling it again is ready at once.
338///
339/// Dropping it after a `notify_one` or `notify_last` reached it, but before
340/// it completed, passes that notification to the next waiter.
341#[must_use = "futures do nothing unless polled"]
342pub struct Notified<'a> {
343    notify: &'a Notify,
344    core: Core,
345}
346
347impl Notified<'_> {
348    /// Adds this future to the waiters that receive `notify_one` and
349    /// `notify_last`, as its first poll would, without registering a waker.
350    /// Polling does the same; this is for a caller that must be queued
351    /// before it checks a condition, so a notification sent in between is
352    /// not stored as a permit for someone else.
353    ///
354    /// `notify_waiters` is received from creation on, enabled or not.
355    ///
356    /// Returns true if the future is ready, which any later poll then
357    /// reports at once. That is so when:
358    ///
359    /// 1. `notify_waiters` was called since the future was created;
360    /// 2. this is the first `enable` or poll and the `Notify` held a
361    ///    permit, which the call consumes; or
362    /// 3. the future was enabled or polled before and has since been
363    ///    notified.
364    ///
365    /// ```
366    /// use nuclei::sync::Notify;
367    /// use std::pin::pin;
368    ///
369    /// let notify = Notify::new();
370    /// let mut waiting = pin!(notify.notified());
371    /// assert!(!waiting.as_mut().enable(), "nothing was sent yet");
372    /// notify.notify_one();
373    /// assert!(waiting.as_mut().enable(), "the one sent after enable is its");
374    /// ```
375    pub fn enable(self: Pin<&mut Self>) -> bool {
376        let this = self.get_mut();
377        this.core.drive(this.notify, None)
378    }
379}
380
381impl Future for Notified<'_> {
382    type Output = ();
383
384    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
385        let this = self.get_mut();
386        if this.core.drive(this.notify, Some(cx.waker())) {
387            Poll::Ready(())
388        } else {
389            Poll::Pending
390        }
391    }
392}
393
394impl Drop for Notified<'_> {
395    fn drop(&mut self) {
396        self.core.cancel(self.notify);
397    }
398}
399
400impl fmt::Debug for Notified<'_> {
401    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402        f.debug_struct("Notified")
403            .field("done", &self.core.done)
404            .finish()
405    }
406}
407
408/// The future [`Notify::notified_owned`] returns: [`Notified`] that keeps
409/// its `Notify` alive itself.
410#[must_use = "futures do nothing unless polled"]
411pub struct OwnedNotified {
412    notify: Arc<Notify>,
413    core: Core,
414}
415
416impl OwnedNotified {
417    /// As [`Notified::enable`].
418    pub fn enable(self: Pin<&mut Self>) -> bool {
419        let this = self.get_mut();
420        this.core.drive(&this.notify, None)
421    }
422}
423
424impl Future for OwnedNotified {
425    type Output = ();
426
427    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
428        let this = self.get_mut();
429        if this.core.drive(&this.notify, Some(cx.waker())) {
430            Poll::Ready(())
431        } else {
432            Poll::Pending
433        }
434    }
435}
436
437impl Drop for OwnedNotified {
438    fn drop(&mut self) {
439        self.core.cancel(&self.notify);
440    }
441}
442
443impl fmt::Debug for OwnedNotified {
444    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
445        f.debug_struct("OwnedNotified")
446            .field("done", &self.core.done)
447            .finish()
448    }
449}
450
451#[cfg(all(test, not(loom)))]
452mod tests {
453    use super::*;
454    use crate::sync::test_support::{Polled, block_on};
455    use core::task::Waker;
456
457    #[test]
458    fn a_notification_before_the_wait_is_kept_once() {
459        let notify = Notify::new();
460        notify.notify_one();
461        notify.notify_one();
462        notify.notify_last();
463        Polled::new(notify.notified()).ready();
464        Polled::new(notify.notified()).pending();
465    }
466
467    #[test]
468    fn notify_one_wakes_waiters_in_order() {
469        let notify = Notify::new();
470        let mut first = Polled::new(notify.notified());
471        first.pending();
472        let mut second = Polled::new(notify.notified());
473        second.pending();
474        notify.notify_one();
475        assert_eq!((first.wakes(), second.wakes()), (1, 0));
476        first.ready();
477        notify.notify_one();
478        second.ready();
479        Polled::new(notify.notified()).pending();
480    }
481
482    #[test]
483    fn notify_last_wakes_the_newest_waiter() {
484        let notify = Notify::new();
485        let mut waiters: Vec<_> = (0..3).map(|_| Polled::new(notify.notified())).collect();
486        for waiter in &mut waiters {
487            waiter.pending();
488        }
489        notify.notify_last();
490        assert_eq!(
491            waiters.iter().map(Polled::wakes).collect::<Vec<_>>(),
492            [0, 0, 1]
493        );
494        notify.notify_last();
495        notify.notify_one();
496        assert_eq!(
497            waiters.iter().map(Polled::wakes).collect::<Vec<_>>(),
498            [1, 1, 1],
499            "one from the back, one from the front"
500        );
501        for waiter in &mut waiters {
502            waiter.ready();
503        }
504    }
505
506    #[test]
507    fn notify_last_skips_the_waiters_that_withdrew_at_the_back() {
508        let notify = Notify::new();
509        let mut oldest = Polled::new(notify.notified());
510        oldest.pending();
511        let mut middle = Polled::new(notify.notified());
512        middle.pending();
513        let mut newest = Polled::new(notify.notified());
514        newest.pending();
515        drop(newest);
516        notify.notify_last();
517        assert_eq!((oldest.wakes(), middle.wakes()), (0, 1));
518        middle.ready();
519        let mut fresh = Polled::new(notify.notified());
520        fresh.pending();
521        drop(fresh);
522        notify.notify_last();
523        assert_eq!(oldest.wakes(), 1, "only the oldest is left");
524        oldest.ready();
525    }
526
527    /// Both ends of the list stay linked through the sweeps that follow
528    /// many withdrawals: a model queue decides who each call must wake.
529    #[test]
530    fn both_ends_stay_linked_after_withdrawals_and_sweeps() {
531        let notify = Notify::new();
532        let mut waiters: Vec<(usize, Polled<Notified<'_>>)> = (0..9)
533            .map(|id| (id, Polled::new(notify.notified())))
534            .collect();
535        for (_, waiter) in &mut waiters {
536            waiter.pending();
537        }
538        // Withdraw the middle of the line, enough of it to sweep.
539        for gone in [4, 5, 3, 6, 2] {
540            let at = waiters
541                .iter()
542                .position(|(id, _)| *id == gone)
543                .expect("queued");
544            drop(waiters.remove(at));
545        }
546        let mut model: std::collections::VecDeque<usize> = [0, 1, 7, 8].into();
547        let mut woken = Vec::new();
548        for call in 0..4 {
549            let expected = if call % 2 == 0 {
550                notify.notify_last();
551                model.pop_back()
552            } else {
553                notify.notify_one();
554                model.pop_front()
555            }
556            .expect("a waiter is left");
557            let (at, _) = waiters
558                .iter()
559                .enumerate()
560                .find(|(_, (_, w))| w.wakes() == 1)
561                .expect("somebody was woken");
562            let (id, mut waiter) = waiters.remove(at);
563            assert_eq!(id, expected, "call {call} woke the wrong waiter");
564            waiter.ready();
565            woken.push(id);
566        }
567        assert_eq!(woken, [8, 0, 7, 1]);
568    }
569
570    #[test]
571    fn notify_waiters_wakes_everyone_present_and_stores_nothing() {
572        let notify = Notify::new();
573        let mut waiting = Polled::new(notify.notified());
574        waiting.pending();
575        let mut created = Polled::new(notify.notified());
576        notify.notify_waiters();
577        waiting.ready();
578        created.ready();
579        Polled::new(notify.notified()).pending();
580    }
581
582    #[test]
583    fn an_older_waiter_queued_behind_a_newer_one_still_gets_the_broadcast() {
584        let notify = Notify::new();
585        // Created before the broadcast, so the broadcast is owed to it.
586        let mut older = notify.notified();
587        notify.notify_waiters();
588        let mut newer = Polled::new(notify.notified());
589        newer.pending();
590        // The older future's first poll passed its generation check before
591        // the broadcast and queues only now, behind the newer waiter: the
592        // rest of that poll, step by step.
593        notify.enqueue(&mut older.core.wait, older.core.generation, Waker::noop());
594        assert!(
595            older.core.wait.poll(&notify.queue, None).is_ready(),
596            "the broadcast after its creation reached it"
597        );
598        newer.pending();
599        assert_eq!(newer.wakes(), 0, "an earlier broadcast is not its");
600    }
601
602    #[test]
603    fn a_dropped_waiter_passes_its_notify_one_on() {
604        let notify = Notify::new();
605        let mut first = Polled::new(notify.notified());
606        first.pending();
607        let mut second = Polled::new(notify.notified());
608        second.pending();
609        notify.notify_one();
610        drop(first);
611        assert_eq!(second.wakes(), 1);
612        second.ready();
613    }
614
615    #[test]
616    fn a_dropped_waiter_passes_its_notify_last_on_to_the_newest() {
617        let notify = Notify::new();
618        let mut oldest = Polled::new(notify.notified());
619        oldest.pending();
620        let mut middle = Polled::new(notify.notified());
621        middle.pending();
622        let mut newest = Polled::new(notify.notified());
623        newest.pending();
624        notify.notify_last();
625        drop(newest);
626        assert_eq!(
627            (oldest.wakes(), middle.wakes()),
628            (0, 1),
629            "the pass-on wakes the newest left"
630        );
631        middle.ready();
632        oldest.pending();
633    }
634
635    #[test]
636    fn enable_queues_the_future_for_notify_one_without_a_poll() {
637        let notify = Notify::new();
638        let mut waiting = core::pin::pin!(notify.notified());
639        assert!(!waiting.as_mut().enable());
640        notify.notify_one();
641        assert!(
642            waiting.as_mut().enable(),
643            "the notification found it queued"
644        );
645        assert!(waiting.as_mut().enable(), "and stays ready");
646        // A permit sent after is left for the next waiter.
647        notify.notify_one();
648        Polled::new(notify.notified()).ready();
649    }
650
651    #[test]
652    fn enable_consumes_a_stored_permit_and_sees_a_broadcast() {
653        let notify = Notify::new();
654        notify.notify_one();
655        let mut got = core::pin::pin!(notify.notified());
656        assert!(got.as_mut().enable(), "the stored permit");
657        Polled::new(notify.notified()).pending();
658
659        let mut broadcast = core::pin::pin!(notify.notified());
660        notify.notify_waiters();
661        assert!(
662            broadcast.as_mut().enable(),
663            "a broadcast after its creation"
664        );
665    }
666
667    #[test]
668    fn a_poll_after_enable_registers_the_real_waker() {
669        let notify = Notify::new();
670        let mut waiting = core::pin::pin!(notify.notified());
671        assert!(!waiting.as_mut().enable());
672        let probe = Polled::new(core::future::pending::<()>());
673        let waker = probe.waker();
674        assert!(
675            waiting
676                .as_mut()
677                .poll(&mut Context::from_waker(&waker))
678                .is_pending()
679        );
680        notify.notify_one();
681        assert_eq!(
682            probe.wakes(),
683            1,
684            "the waker of the poll replaced the empty one"
685        );
686        assert!(
687            waiting
688                .as_mut()
689                .poll(&mut Context::from_waker(&waker))
690                .is_ready()
691        );
692    }
693
694    #[test]
695    fn an_enabled_future_is_ahead_of_one_polled_later() {
696        let notify = Notify::new();
697        let mut enabled = core::pin::pin!(notify.notified());
698        assert!(!enabled.as_mut().enable());
699        let mut polled = Polled::new(notify.notified());
700        polled.pending();
701        notify.notify_one();
702        assert!(
703            enabled.as_mut().enable(),
704            "the enabled one is first in line"
705        );
706        assert_eq!(polled.wakes(), 0);
707        notify.notify_one();
708        assert_eq!(polled.wakes(), 1);
709        polled.ready();
710    }
711
712    #[test]
713    fn an_enabled_future_dropped_after_its_notification_passes_it_on() {
714        let notify = Notify::new();
715        let mut enabled = Box::pin(notify.notified());
716        assert!(!enabled.as_mut().enable());
717        let mut next = Polled::new(notify.notified());
718        next.pending();
719        notify.notify_one();
720        drop(enabled);
721        assert_eq!(next.wakes(), 1, "the unseen notification moved on");
722        next.ready();
723    }
724
725    #[test]
726    fn an_owned_notified_outlives_the_borrow() {
727        let notify = Arc::new(Notify::new());
728        let mut waiting = Polled::new(Arc::clone(&notify).notified_owned());
729        waiting.pending();
730        notify.notify_one();
731        waiting.ready();
732        let owned = Arc::clone(&notify).notified_owned();
733        drop(notify);
734        let mut owned = core::pin::pin!(owned);
735        assert!(!owned.as_mut().enable());
736    }
737
738    #[test]
739    fn a_const_notify_works_in_a_static() {
740        static NOTIFY: Notify = Notify::const_new();
741        NOTIFY.notify_one();
742        Polled::new(NOTIFY.notified()).ready();
743    }
744
745    #[test]
746    fn one_notification_reaches_a_waiter_on_another_thread_whenever_it_lands() {
747        let rounds = if cfg!(miri) { 5 } else { 200 };
748        for _ in 0..rounds {
749            let notify = Arc::new(Notify::new());
750            let waiter = Arc::clone(&notify);
751            let thread = std::thread::spawn(move || block_on(waiter.notified()));
752            notify.notify_one();
753            thread.join().expect("waiter");
754        }
755    }
756}