Skip to main content

gpui_ce_motion/
completion.rs

1//! Optional completion futures. Only callers requesting a future allocate.
2use std::{
3    future::Future,
4    pin::Pin,
5    sync::{Arc, Mutex, Weak},
6    task::{Context, Poll, Waker},
7};
8
9/// Result of a trajectory observed by a completion future.
10#[derive(Clone, Copy, Debug, PartialEq, Eq)]
11pub enum CompletionStatus {
12    /// The trajectory reached its endpoint, including reduced-motion completion.
13    Completed,
14    /// It was replaced, explicitly cancelled, restarted, or its owner was dropped.
15    Cancelled,
16}
17
18#[derive(Debug, Default)]
19struct ResultState {
20    result: Option<CompletionStatus>,
21    waker: Option<Waker>,
22}
23
24/// A single observer of playback completion. Polling never starts a timer or
25/// executor; the retained player must continue being sampled by its host.
26#[derive(Debug)]
27pub struct Completion(Arc<Mutex<ResultState>>);
28
29impl Future for Completion {
30    type Output = CompletionStatus;
31
32    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
33        let mut state = self.0.lock().unwrap_or_else(|error| error.into_inner());
34
35        if let Some(result) = state.result {
36            return Poll::Ready(result);
37        }
38
39        if !state
40            .waker
41            .as_ref()
42            .is_some_and(|waker| waker.will_wake(cx.waker()))
43        {
44            state.waker = Some(cx.waker().clone());
45        }
46
47        Poll::Pending
48    }
49}
50
51#[derive(Debug, Default)]
52pub(crate) struct CompletionSource {
53    observers: Vec<Weak<Mutex<ResultState>>>,
54}
55
56impl CompletionSource {
57    pub(crate) fn subscribe(&mut self, complete: bool) -> Completion {
58        self.observers
59            .retain(|observer| observer.strong_count() > 0);
60        let result = complete.then_some(CompletionStatus::Completed);
61
62        let state = Arc::new(Mutex::new(ResultState {
63            result,
64            waker: None,
65        }));
66
67        if !complete {
68            self.observers.push(Arc::downgrade(&state));
69        }
70
71        Completion(state)
72    }
73
74    pub(crate) fn resolve(&mut self, result: CompletionStatus) {
75        for observer in self.observers.drain(..) {
76            if let Some(observer) = observer.upgrade() {
77                let waker = {
78                    let mut state = observer.lock().unwrap_or_else(|error| error.into_inner());
79
80                    state.result = Some(result);
81
82                    state.waker.take()
83                };
84
85                if let Some(waker) = waker {
86                    waker.wake();
87                }
88            }
89        }
90    }
91}
92
93impl Drop for CompletionSource {
94    fn drop(&mut self) {
95        self.resolve(CompletionStatus::Cancelled);
96    }
97}