Skip to main content

commonware_utils/futures/
shared.rs

1//! A cloneable future whose clones share one output (see [Shared]).
2
3use crate::sync::Mutex;
4use futures::task::{ArcWake, waker_ref};
5use std::{
6    future::Future,
7    mem,
8    pin::Pin,
9    sync::{
10        Arc, Weak,
11        atomic::{AtomicUsize, Ordering},
12    },
13    task::{Context, Poll, Waker},
14};
15
16/// Number of wakers collected without allocating when waking several clones at once.
17const INLINE_WAKES: usize = 4;
18
19/// A cloneable future that drives `F` through whichever clone is polled and resolves every clone
20/// to a clone of its output.
21///
22/// Several tasks can wait on one future without a task of its own, and each completes even if the
23/// clone that created the future is never polled again. Clones complete together, and a clone
24/// polled after completion resolves immediately. Dropping the last clone drops the inner future,
25/// or its output, after which no [WeakShared] handle can recover it.
26///
27/// Polling requires `F` to be [Unpin] (box it first otherwise) and its output to be [Clone].
28/// The shared state is itself the inner future's waker, and a waker must be `'static`, [Send],
29/// and [Sync], so `F` must also be [Send] and `'static`, and its output [Send] and [Sync].
30///
31/// # Liveness
32///
33/// Exactly one clone polls the inner future at a time. A clone polled meanwhile registers its
34/// waker and returns [Poll::Pending] without waiting for that poll. A clone's waker stays
35/// registered until the clone completes or is dropped, and waking the inner future wakes every
36/// registered clone. If the inner future is woken while a clone polls it, or another clone finds
37/// it busy meanwhile, the polling clone wakes every other clone again once it stops polling, so a
38/// clone that went back to sleep after finding the inner future busy observes what that poll did
39/// and polls the inner future if it was woken. Progress therefore never depends on any particular
40/// clone being polled again. A clone may stop polling, because it is dropped or finished through
41/// another path, without stranding the others. A clone polled when the inner future was not woken
42/// since its last poll only registers, so the inner future is polled about once per wake however
43/// many clones are woken.
44///
45/// # Panics
46///
47/// A panic while polling the inner future propagates to the polling clone and poisons the future.
48/// Every waiting clone is woken, and polling any clone afterwards panics.
49///
50/// # Wakers
51///
52/// Registered wakers are cloned while the shared state is locked, and that lock is not reentrant,
53/// so cloning a registered waker must not wake this future's inner future, or poll or drop one of
54/// its clones. Wakes, and drops of displaced wakers, happen after unlocking.
55#[must_use = "futures do nothing unless you `.await` or poll them"]
56pub struct Shared<F: Future> {
57    inner: Arc<Inner<F>>,
58    /// This clone's slot in [State::wakers], assigned when it first waits.
59    key: Option<usize>,
60}
61
62/// A weak handle to a [Shared] that does not keep its future alive.
63pub struct WeakShared<F: Future>(Weak<Inner<F>>);
64
65/// The state every clone of a [Shared] refers to.
66///
67/// It is also the inner future's waker, so wakers the inner future hands out keep this allocation
68/// alive, possibly after every clone is dropped. The clones therefore count themselves, and the
69/// last one releases the future or its output (see [Stage::Released]).
70struct Inner<F: Future> {
71    /// Number of live [Shared] clones. Once zero, it never increases again.
72    clones: AtomicUsize,
73    state: Mutex<State<F>>,
74}
75
76struct State<F: Future> {
77    stage: Stage<F>,
78    /// Whether the inner future was woken since a clone last started polling it, or was never
79    /// polled. While it is unset, the inner future cannot make progress, so clones only register.
80    woken: bool,
81    /// Whether a clone found the inner future busy since a clone last started polling it.
82    contended: bool,
83    /// The waker of each clone waiting on the future, indexed by the clone's key. Completion
84    /// takes them all.
85    wakers: Vec<Option<Waker>>,
86    /// Keys of vacant slots in `wakers`.
87    free: Vec<usize>,
88}
89
90enum Stage<F: Future> {
91    /// No clone is polling the inner future.
92    Idle(F),
93    /// A clone took the inner future out of the state to poll it without holding the lock.
94    Polling,
95    /// The inner future completed. Clones of the output are made outside the lock, since
96    /// cloning it may wake the inner future, which locks the state.
97    Ready(Arc<F::Output>),
98    /// The inner future panicked.
99    Poisoned,
100    /// Every clone was dropped, and the last one dropped the future or its output.
101    Released,
102}
103
104/// Clones of registered wakers, collected under the lock and woken after releasing it. The first
105/// few are stored inline, so waking a few clones does not allocate.
106struct Wakes {
107    inline: [Option<Waker>; INLINE_WAKES],
108    spilled: Vec<Waker>,
109}
110
111impl Wakes {
112    fn wake(self) {
113        for waker in self.inline.into_iter().flatten().chain(self.spilled) {
114            waker.wake();
115        }
116    }
117}
118
119impl<F: Future> State<F> {
120    /// Register `waker` for the clone with `key`, assigning the clone a key if it has none.
121    ///
122    /// Returns the waker it replaces, if any, for the caller to drop after releasing the lock,
123    /// since a waker's destructor may run arbitrary code, including dropping another clone.
124    #[must_use]
125    fn register(&mut self, key: &mut Option<usize>, waker: &Waker) -> Option<Waker> {
126        let key = *key.get_or_insert_with(|| {
127            self.free.pop().unwrap_or_else(|| {
128                self.wakers.push(None);
129                self.wakers.len() - 1
130            })
131        });
132        let slot = &mut self.wakers[key];
133        if slot
134            .as_ref()
135            .is_some_and(|registered| registered.will_wake(waker))
136        {
137            return None;
138        }
139        slot.replace(waker.clone())
140    }
141
142    /// Remove the registration of the clone with `key`, returning its waker for the caller to
143    /// drop after releasing the lock (see [Self::register]).
144    #[must_use]
145    fn deregister(&mut self, key: usize) -> Option<Waker> {
146        // Completion and poisoning take every registration, leaving no slot to vacate.
147        let waker = self.wakers.get_mut(key)?.take();
148        self.free.push(key);
149        waker
150    }
151
152    /// Clone every registered waker except the one with key `except`.
153    fn wakes(&self, except: Option<usize>) -> Wakes {
154        let mut wakes = Wakes {
155            inline: Default::default(),
156            spilled: Vec::new(),
157        };
158        let mut inline = wakes.inline.iter_mut();
159        let registered = self.wakers.iter().enumerate();
160        let others = registered.filter(|&(key, _)| except != Some(key));
161        for waker in others.filter_map(|(_, waker)| waker.as_ref()) {
162            match inline.next() {
163                Some(slot) => *slot = Some(waker.clone()),
164                None => wakes.spilled.push(waker.clone()),
165            }
166        }
167        wakes
168    }
169
170    /// Move to the terminal `stage`, returning every registered waker for the caller to wake
171    /// after releasing the lock.
172    fn finish(&mut self, stage: Stage<F>) -> Vec<Option<Waker>> {
173        self.stage = stage;
174        mem::take(&mut self.wakers)
175    }
176}
177
178impl<F: Future> Shared<F> {
179    /// Share `future` among the clones of the returned [Shared].
180    pub fn new(future: F) -> Self {
181        Self {
182            inner: Arc::new(Inner {
183                clones: AtomicUsize::new(1),
184                state: Mutex::new(State {
185                    stage: Stage::Idle(future),
186                    woken: true,
187                    contended: false,
188                    wakers: Vec::new(),
189                    free: Vec::new(),
190                }),
191            }),
192            key: None,
193        }
194    }
195
196    /// Create a [WeakShared] handle to this future.
197    pub fn downgrade(&self) -> WeakShared<F> {
198        WeakShared(Arc::downgrade(&self.inner))
199    }
200
201    /// Whether `self` and `other` are clones of the same future, whether or not it completed.
202    pub fn ptr_eq(&self, other: &Self) -> bool {
203        Arc::ptr_eq(&self.inner, &other.inner)
204    }
205}
206
207impl<F: Future> Clone for Shared<F> {
208    fn clone(&self) -> Self {
209        self.inner.clones.fetch_add(1, Ordering::Relaxed);
210        Self {
211            inner: self.inner.clone(),
212            key: None,
213        }
214    }
215}
216
217impl<F: Future> Drop for Shared<F> {
218    fn drop(&mut self) {
219        // Finish this clone's bookkeeping before running any destructor, since a destructor may
220        // panic: deregister its waker and, as the last clone, take the future or output out of
221        // the state. Both are dropped afterwards, outside the lock (see [State::register]).
222        let waker = self
223            .key
224            .and_then(|key| self.inner.state.lock().deregister(key));
225        let released = (self.inner.clones.fetch_sub(1, Ordering::AcqRel) == 1)
226            .then(|| mem::replace(&mut self.inner.state.lock().stage, Stage::Released));
227        drop(waker);
228        drop(released);
229    }
230}
231
232impl<F> Future for Shared<F>
233where
234    F: Future + Send + Unpin + 'static,
235    F::Output: Clone + Send + Sync,
236{
237    type Output = F::Output;
238
239    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<F::Output> {
240        let this = self.get_mut();
241
242        // Register this clone, and take the inner future out to poll it unless another clone is
243        // polling it.
244        let (mut future, replaced) = {
245            let mut guard = this.inner.state.lock();
246            let state = &mut *guard;
247            match &state.stage {
248                Stage::Idle(_) if state.woken => {}
249                Stage::Idle(_) | Stage::Polling => {
250                    state.contended |= matches!(state.stage, Stage::Polling);
251                    let replaced = state.register(&mut this.key, cx.waker());
252                    drop(guard);
253                    drop(replaced);
254                    return Poll::Pending;
255                }
256                Stage::Ready(output) => {
257                    // Completion removed every registration.
258                    this.key = None;
259                    let output = Arc::clone(output);
260                    drop(guard);
261                    return Poll::Ready((*output).clone());
262                }
263                Stage::Poisoned => panic!("Shared future polled after its inner future panicked"),
264                Stage::Released => unreachable!("a live clone keeps the future"),
265            }
266            let replaced = state.register(&mut this.key, cx.waker());
267            state.woken = false;
268            state.contended = false;
269            let Stage::Idle(future) = mem::replace(&mut state.stage, Stage::Polling) else {
270                unreachable!("stage checked above");
271            };
272            (future, replaced)
273        };
274
275        // Poll, and clone any output, without holding the lock, so wakes and other clones never
276        // wait on the inner future. Unwinding out of either, or out of dropping the replaced
277        // waker, poisons the future, which another clone could otherwise never find idle again.
278        let poison = Poison(&this.inner);
279        drop(replaced);
280        let waker = waker_ref(&this.inner);
281        let poll = Pin::new(&mut future)
282            .poll(&mut Context::from_waker(&waker))
283            .map(|output| {
284                let shared = Arc::new(output);
285                ((*shared).clone(), shared)
286            });
287        mem::forget(poison);
288
289        let mut state = this.inner.state.lock();
290        match poll {
291            Poll::Pending => {
292                state.stage = Stage::Idle(future);
293                if !state.woken && !state.contended {
294                    return Poll::Pending;
295                }
296
297                // Clones that found the inner future busy went back to sleep without observing
298                // this poll or any wake during it, so wake them now. A wake during the poll also
299                // woke this clone's own waker.
300                let wakes = state.wakes(this.key);
301                drop(state);
302                wakes.wake();
303                Poll::Pending
304            }
305            Poll::Ready((output, shared)) => {
306                let own = this.key.take().and_then(|key| state.wakers[key].take());
307                let wakers = state.finish(Stage::Ready(shared));
308                drop(state);
309                drop(own);
310                for waker in wakers.into_iter().flatten() {
311                    waker.wake();
312                }
313                Poll::Ready(output)
314            }
315        }
316    }
317}
318
319impl<F: Future> WeakShared<F> {
320    /// Recover a [Shared] clone, unless every [Shared] clone has been dropped.
321    pub fn upgrade(&self) -> Option<Shared<F>> {
322        let inner = self.0.upgrade()?;
323        inner
324            .clones
325            .try_update(Ordering::Relaxed, Ordering::Relaxed, |clones| {
326                (clones != 0).then_some(clones + 1)
327            })
328            .ok()?;
329        Some(Shared { inner, key: None })
330    }
331}
332
333impl<F: Future> Clone for WeakShared<F> {
334    fn clone(&self) -> Self {
335        Self(self.0.clone())
336    }
337}
338
339impl<F> ArcWake for Inner<F>
340where
341    F: Future + Send,
342    F::Output: Send + Sync,
343{
344    fn wake_by_ref(arc_self: &Arc<Self>) {
345        let wakes = {
346            let mut state = arc_self.state.lock();
347            state.woken = true;
348            state.wakes(None)
349        };
350        wakes.wake();
351    }
352}
353
354/// Poisons a [Shared] when dropped, which happens only if polling its inner future unwinds.
355struct Poison<'a, F: Future>(&'a Inner<F>);
356
357impl<F: Future> Drop for Poison<'_, F> {
358    fn drop(&mut self) {
359        // Wake every waiting clone so it observes the panic instead of waiting forever.
360        let wakers = self.0.state.lock().finish(Stage::Poisoned);
361        for waker in wakers.into_iter().flatten() {
362            waker.wake();
363        }
364    }
365}
366
367#[cfg(test)]
368mod tests {
369    use super::*;
370    use futures::{
371        FutureExt as _,
372        executor::block_on,
373        future::{self, BoxFuture},
374        task,
375    };
376    use std::{
377        panic::{self, AssertUnwindSafe},
378        sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
379        thread,
380        time::Duration,
381    };
382
383    /// A waker that counts its wakes.
384    struct Counter(AtomicUsize);
385
386    impl Counter {
387        fn count(&self) -> usize {
388            self.0.load(SeqCst)
389        }
390    }
391
392    impl ArcWake for Counter {
393        fn wake_by_ref(arc_self: &Arc<Self>) {
394            arc_self.0.fetch_add(1, SeqCst);
395        }
396    }
397
398    /// A waker and the counter of its wakes.
399    fn counter() -> (Arc<Counter>, Waker) {
400        let counter = Arc::new(Counter(AtomicUsize::new(0)));
401        (counter.clone(), task::waker(counter))
402    }
403
404    fn poll<F>(shared: &mut Shared<F>, waker: &Waker) -> Poll<F::Output>
405    where
406        F: Future + Send + Unpin + 'static,
407        F::Output: Clone + Send + Sync,
408    {
409        Pin::new(shared).poll(&mut Context::from_waker(waker))
410    }
411
412    /// Controls an inner future that the tests wake and complete by hand.
413    #[derive(Default)]
414    struct Control {
415        /// The waker of the inner future's latest poll.
416        waker: Mutex<Option<Waker>>,
417        /// Runs once during the next poll of the inner future, after it decides its result.
418        hook: Mutex<Option<Box<dyn FnOnce() + Send>>>,
419        /// Whether the inner future's next poll resolves.
420        ready: AtomicBool,
421        /// Polls of the inner future.
422        polls: AtomicUsize,
423    }
424
425    impl Control {
426        /// The inner future, which resolves to 7 once [Self::ready] is set.
427        fn future(self: &Arc<Self>) -> BoxFuture<'static, u32> {
428            let control = self.clone();
429            future::poll_fn(move |cx| {
430                control.polls.fetch_add(1, SeqCst);
431                *control.waker.lock() = Some(cx.waker().clone());
432                let ready = control.ready.load(SeqCst);
433                let hook = control.hook.lock().take();
434                if let Some(hook) = hook {
435                    hook();
436                }
437                if ready { Poll::Ready(7) } else { Poll::Pending }
438            })
439            .boxed()
440        }
441
442        /// Wake the inner future, as the event it waits on would.
443        fn wake(&self) {
444            self.waker
445                .lock()
446                .as_ref()
447                .expect("inner future never polled")
448                .wake_by_ref();
449        }
450    }
451
452    #[test]
453    fn test_clones_share_output_and_poll_one_at_a_time() {
454        const CLONES: usize = 8;
455        const POLLS: usize = 1_000;
456
457        // The inner future wakes itself until its last poll, so every clone keeps polling it from
458        // its own thread.
459        let polls = Arc::new(AtomicUsize::new(0));
460        let shared = {
461            let active = AtomicBool::new(false);
462            let polls = polls.clone();
463            Shared::new(future::poll_fn(move |cx| {
464                assert!(
465                    !active.swap(true, SeqCst),
466                    "inner future polled concurrently"
467                );
468                thread::yield_now();
469                let polled = polls.fetch_add(1, SeqCst) + 1;
470                active.store(false, SeqCst);
471                if polled == POLLS {
472                    return Poll::Ready(Arc::new(polled));
473                }
474                cx.waker().wake_by_ref();
475                Poll::Pending
476            }))
477        };
478        let outputs: Vec<_> = (0..CLONES)
479            .map(|_| {
480                let shared = shared.clone();
481                thread::spawn(move || block_on(shared))
482            })
483            .collect::<Vec<_>>()
484            .into_iter()
485            .map(|handle| handle.join().unwrap())
486            .collect();
487
488        // Every clone resolved to a clone of the one output.
489        for output in &outputs {
490            assert!(Arc::ptr_eq(output, &outputs[0]));
491        }
492        assert_eq!(*outputs[0], POLLS);
493        assert_eq!(polls.load(SeqCst), POLLS);
494    }
495
496    #[test]
497    fn test_clone_after_completion_resolves() {
498        let shared = Shared::new(future::ready(5u32));
499        assert_eq!(block_on(shared.clone()), 5);
500        let (wakes, waker) = counter();
501        let mut late = shared.clone();
502        assert_eq!(poll(&mut late, &waker), Poll::Ready(5));
503        assert_eq!(poll(&mut late, &waker), Poll::Ready(5));
504        let mut upgraded = shared.downgrade().upgrade().expect("strong clone alive");
505        assert_eq!(poll(&mut upgraded, &waker), Poll::Ready(5));
506        assert_eq!(wakes.count(), 0);
507
508        // Completion does not change identity.
509        assert!(late.ptr_eq(&shared));
510        assert!(!late.ptr_eq(&Shared::new(future::ready(5))));
511    }
512
513    #[test]
514    fn test_wake_during_poll_rewakes_clone_polled_meanwhile() {
515        let control = Arc::new(Control::default());
516        let a = Arc::new(Mutex::new(Shared::new(control.future())));
517        let mut b = a.lock().clone();
518        let (a_wakes, a_waker) = counter();
519        let (b_wakes, b_waker) = counter();
520
521        // A polls the inner future, which waits. An earlier event then wakes it, which wakes A.
522        assert!(poll(&mut a.lock(), &a_waker).is_pending());
523        control.wake();
524        assert_eq!(a_wakes.count(), 1);
525
526        // B polls the inner future before A does. After the inner future decides to wait, its
527        // final event arrives and wakes it, and A, polled meanwhile, finds B polling and goes
528        // back to sleep.
529        let parked = Arc::new(AtomicUsize::new(0));
530        *control.hook.lock() = Some(Box::new({
531            let (control, a, a_waker, a_wakes, parked) = (
532                control.clone(),
533                a.clone(),
534                a_waker.clone(),
535                a_wakes.clone(),
536                parked.clone(),
537            );
538            move || {
539                control.ready.store(true, SeqCst);
540                control.wake();
541                assert!(poll(&mut a.lock(), &a_waker).is_pending());
542                parked.store(a_wakes.count(), SeqCst);
543            }
544        }));
545        assert!(poll(&mut b, &b_waker).is_pending());
546        assert_eq!(control.polls.load(SeqCst), 2);
547
548        // Finishing that poll wakes A again, but not B, whose own waker the final event already
549        // woke. B can leave without polling again and A still completes the inner future.
550        assert!(a_wakes.count() > parked.load(SeqCst));
551        assert_eq!(b_wakes.count(), 1);
552        drop(b);
553        assert_eq!(poll(&mut a.lock(), &a_waker), Poll::Ready(7));
554        assert_eq!(control.polls.load(SeqCst), 3);
555    }
556
557    #[test]
558    fn test_clone_finding_future_busy_is_woken_after_poll() {
559        let control = Arc::new(Control::default());
560        let a = Arc::new(Mutex::new(Shared::new(control.future())));
561        let mut b = a.lock().clone();
562        let (a_wakes, a_waker) = counter();
563        let (b_wakes, b_waker) = counter();
564
565        // While B polls the inner future, which is not woken, A finds it busy and waits.
566        *control.hook.lock() = Some(Box::new({
567            let a = a.clone();
568            move || assert!(poll(&mut a.lock(), &a_waker).is_pending())
569        }));
570        assert!(poll(&mut b, &b_waker).is_pending());
571
572        // B's poll may have done what A waits for, so finishing it wakes A, but not B.
573        assert_eq!((a_wakes.count(), b_wakes.count()), (1, 0));
574    }
575
576    #[test]
577    fn test_dropped_woken_clone_leaves_others_woken() {
578        let control = Arc::new(Control::default());
579        let mut a = Shared::new(control.future());
580        let mut b = a.clone();
581        let (a_wakes, a_waker) = counter();
582        let (b_wakes, b_waker) = counter();
583        assert!(poll(&mut a, &a_waker).is_pending());
584        assert!(poll(&mut b, &b_waker).is_pending());
585
586        // The event the inner future waits on wakes both clones, and A is dropped before it is
587        // polled again.
588        control.ready.store(true, SeqCst);
589        control.wake();
590        assert_eq!((a_wakes.count(), b_wakes.count()), (1, 1));
591        drop(a);
592
593        // The dropped clone is no longer registered, and B completes the inner future.
594        control.wake();
595        assert_eq!((a_wakes.count(), b_wakes.count()), (1, 2));
596        assert_eq!(poll(&mut b, &b_waker), Poll::Ready(7));
597    }
598
599    #[test]
600    fn test_last_clone_drops_future_despite_retained_waker() {
601        struct DropFlag(Arc<AtomicBool>);
602
603        impl Drop for DropFlag {
604            fn drop(&mut self) {
605                self.0.store(true, SeqCst);
606            }
607        }
608
609        // The inner future hands its waker to a registration that outlives it, as an event source
610        // would.
611        let dropped = Arc::new(AtomicBool::new(false));
612        let registration: Arc<Mutex<Option<Waker>>> = Arc::default();
613        let mut shared = {
614            let flag = DropFlag(dropped.clone());
615            let registration = registration.clone();
616            Shared::new(
617                async move {
618                    let _flag = flag;
619                    future::poll_fn(|cx| {
620                        *registration.lock() = Some(cx.waker().clone());
621                        Poll::<u32>::Pending
622                    })
623                    .await
624                }
625                .boxed(),
626            )
627        };
628        let (_, waker) = counter();
629        assert!(poll(&mut shared, &waker).is_pending());
630        let weak = shared.downgrade();
631        let upgraded = weak.upgrade().expect("strong clone alive");
632        assert!(upgraded.ptr_eq(&shared));
633
634        // Only the last clone drops the future, after which upgrading fails and the retained waker
635        // wakes nothing.
636        drop(shared);
637        assert!(!dropped.load(SeqCst));
638        drop(upgraded);
639        assert!(dropped.load(SeqCst));
640        assert!(weak.clone().upgrade().is_none());
641        registration.lock().take().unwrap().wake();
642        assert!(weak.upgrade().is_none());
643    }
644
645    #[test]
646    #[should_panic(expected = "Shared future polled after its inner future panicked")]
647    fn test_panic_poisons_every_clone() {
648        // The inner future wakes itself before waiting, so the next clone polled polls it again.
649        let mut polled = false;
650        let mut a = Shared::new(future::poll_fn(move |cx| -> Poll<u32> {
651            assert!(!polled, "inner future failed");
652            polled = true;
653            cx.waker().wake_by_ref();
654            Poll::Pending
655        }));
656        let mut b = a.clone();
657        let (_, a_waker) = counter();
658        let (b_wakes, b_waker) = counter();
659        assert!(poll(&mut b, &b_waker).is_pending());
660        let woken = b_wakes.count();
661
662        // The panic reaches the polling clone and wakes the waiting one, which then panics too.
663        let panicked = panic::catch_unwind(AssertUnwindSafe(|| poll(&mut a, &a_waker)));
664        assert!(panicked.is_err());
665        assert_eq!(b_wakes.count(), woken + 1);
666        let _ = poll(&mut b, &b_waker);
667    }
668
669    #[test]
670    fn test_clones_poll_inner_future_once_per_wake() {
671        const CLONES: usize = 8;
672
673        let control = Arc::new(Control::default());
674        let shared = Shared::new(control.future());
675        let mut clones: Vec<_> = (0..CLONES).map(|_| shared.clone()).collect();
676        drop(shared);
677        let (wakes, waker) = counter();
678
679        // Only the first clone polls the inner future, which is not woken afterwards.
680        for clone in &mut clones {
681            assert!(poll(clone, &waker).is_pending());
682        }
683        assert_eq!(control.polls.load(SeqCst), 1);
684
685        // A wake reaches every clone, and only the first clone polled afterwards polls the inner
686        // future.
687        control.wake();
688        assert_eq!(wakes.count(), CLONES);
689        for clone in &mut clones {
690            assert!(poll(clone, &waker).is_pending());
691        }
692        assert_eq!(control.polls.load(SeqCst), 2);
693
694        // Every clone resolves after the final wake, which the first clone polls through.
695        control.ready.store(true, SeqCst);
696        control.wake();
697        for clone in &mut clones {
698            assert_eq!(poll(clone, &waker), Poll::Ready(7));
699        }
700        assert_eq!(control.polls.load(SeqCst), 3);
701    }
702
703    /// A waker whose destructor panics.
704    struct PanicsOnDrop;
705
706    impl ArcWake for PanicsOnDrop {
707        fn wake_by_ref(_: &Arc<Self>) {}
708    }
709
710    impl Drop for PanicsOnDrop {
711        fn drop(&mut self) {
712            panic!("waker destructor failed");
713        }
714    }
715
716    #[test]
717    #[should_panic(expected = "Shared future polled after its inner future panicked")]
718    fn test_panicking_replaced_waker_poisons_every_clone() {
719        // The inner future wakes itself before waiting, so A polls it again below.
720        let mut a = Shared::new(future::poll_fn(|cx| -> Poll<u32> {
721            cx.waker().wake_by_ref();
722            Poll::Pending
723        }));
724        let mut b = a.clone();
725        let (_, plain) = counter();
726        assert!(poll(&mut a, &task::waker(Arc::new(PanicsOnDrop))).is_pending());
727        assert!(poll(&mut b, &plain).is_pending());
728
729        // Re-registering A drops its replaced waker, whose destructor panics while A holds the
730        // inner future. B observes the panic instead of finding the future busy forever.
731        let panicked = panic::catch_unwind(AssertUnwindSafe(|| poll(&mut a, &plain)));
732        assert!(panicked.is_err());
733        let _ = poll(&mut b, &plain);
734    }
735
736    /// Runs `f` on its own thread and fails instead of waiting forever if it does not return, since
737    /// a regression that re-enters the state lock would otherwise deadlock the test.
738    fn completes(f: impl FnOnce() + Send + 'static) {
739        let (done, finished) = std::sync::mpsc::channel();
740        thread::spawn(move || {
741            f();
742            let _ = done.send(());
743        });
744        finished
745            .recv_timeout(Duration::from_secs(10))
746            .expect("call re-entered the shared state and deadlocked");
747    }
748
749    /// An output whose clones wake the inner future that produced it.
750    struct WakingOutput(Arc<Mutex<Option<Waker>>>);
751
752    impl Clone for WakingOutput {
753        fn clone(&self) -> Self {
754            if let Some(waker) = self.0.lock().as_ref() {
755                waker.wake_by_ref();
756            }
757            Self(self.0.clone())
758        }
759    }
760
761    #[test]
762    fn test_output_clone_may_wake_inner_future() {
763        completes(|| {
764            let registered = Arc::new(Mutex::new(None));
765            let mut a = Shared::new(future::poll_fn(move |cx| {
766                *registered.lock() = Some(cx.waker().clone());
767                Poll::Ready(WakingOutput(registered.clone()))
768            }));
769            let mut b = a.clone();
770            let (_, waker) = counter();
771
772            // Both the completing clone and a clone polled afterwards clone the output, which
773            // wakes the inner future's retained waker.
774            assert!(poll(&mut a, &waker).is_ready());
775            assert!(poll(&mut b, &waker).is_ready());
776        });
777    }
778
779    /// A waker that drops a registered clone of a [Shared] when it is dropped.
780    struct DropsClone(Mutex<Option<Shared<BoxFuture<'static, ()>>>>);
781
782    impl ArcWake for DropsClone {
783        fn wake_by_ref(_: &Arc<Self>) {}
784    }
785
786    impl Drop for DropsClone {
787        fn drop(&mut self) {
788            drop(self.0.lock().take());
789        }
790    }
791
792    /// A registered waker whose destructor drops `sibling`, a registered clone of the future.
793    fn dropping_waker(sibling: Shared<BoxFuture<'static, ()>>) -> Waker {
794        task::waker(Arc::new(DropsClone(Mutex::new(Some(sibling)))))
795    }
796
797    #[rstest::rstest]
798    #[case::replaced(true)]
799    #[case::dropped(false)]
800    fn test_destroyed_waker_may_drop_a_registered_clone(#[case] replaced: bool) {
801        completes(move || {
802            let mut a = Shared::new(future::pending::<()>().boxed());
803            let mut b = a.clone();
804            let (_, plain) = counter();
805            assert!(poll(&mut b, &plain).is_pending());
806            let waker = dropping_waker(b);
807            assert!(poll(&mut a, &waker).is_pending());
808            drop(waker);
809
810            // Re-registering A with another waker, or dropping A, destroys its registered waker,
811            // which drops the other clone and removes its registration.
812            if replaced {
813                assert!(poll(&mut a, &plain).is_pending());
814            } else {
815                drop(a);
816            }
817        });
818    }
819
820    #[test]
821    fn test_last_drop_with_panicking_waker_releases_future() {
822        struct DropFlag(Arc<AtomicBool>);
823
824        impl Drop for DropFlag {
825            fn drop(&mut self) {
826                self.0.store(true, SeqCst);
827            }
828        }
829
830        // The inner future hands its waker to a registration that outlives every clone, as an
831        // event source would, so only the last clone's drop can release the future.
832        let dropped = Arc::new(AtomicBool::new(false));
833        let registration: Arc<Mutex<Option<Waker>>> = Arc::default();
834        let mut shared = {
835            let flag = DropFlag(dropped.clone());
836            let registration = registration.clone();
837            Shared::new(
838                async move {
839                    let _flag = flag;
840                    future::poll_fn(|cx| {
841                        *registration.lock() = Some(cx.waker().clone());
842                        Poll::<u32>::Pending
843                    })
844                    .await
845                }
846                .boxed(),
847            )
848        };
849        let weak = shared.downgrade();
850        let waker = task::waker(Arc::new(PanicsOnDrop));
851        assert!(poll(&mut shared, &waker).is_pending());
852        drop(waker);
853
854        // The registered waker's destructor panics while the last clone drops. The clone still
855        // releases the future, so the weak handle cannot recover it, although the retained waker
856        // keeps the shared allocation alive.
857        let unwound = panic::catch_unwind(AssertUnwindSafe(|| drop(shared)));
858        assert!(unwound.is_err());
859        assert!(dropped.load(SeqCst));
860        assert!(weak.upgrade().is_none());
861        assert!(registration.lock().is_some());
862    }
863}