Skip to main content

veilid_tools/
eventual_value.rs

1use super::*;
2
3use eventual_base::*;
4
5pub struct EventualValue<T: Unpin> {
6    inner: Arc<Mutex<EventualBaseInner<T>>>,
7}
8
9impl<T: Unpin> core::fmt::Debug for EventualValue<T> {
10    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11        f.debug_struct("EventualValue").finish()
12    }
13}
14
15impl<T: Unpin> Clone for EventualValue<T> {
16    fn clone(&self) -> Self {
17        Self {
18            inner: self.inner.clone(),
19        }
20    }
21}
22
23impl<T: Unpin> EventualBase for EventualValue<T> {
24    type ResolvedType = T;
25    fn base_inner(&self) -> MutexGuard<'_, EventualBaseInner<Self::ResolvedType>> {
26        self.inner.lock()
27    }
28}
29
30impl<T: Unpin> Default for EventualValue<T> {
31    fn default() -> Self {
32        Self::new()
33    }
34}
35
36impl<T: Unpin> EventualValue<T> {
37    #[must_use]
38    pub fn new() -> Self {
39        Self {
40            inner: Arc::new(Mutex::new(EventualBaseInner::new())),
41        }
42    }
43
44    #[must_use]
45    pub fn instance(&self) -> EventualValueFuture<T> {
46        EventualValueFuture {
47            id: None,
48            eventual: self.clone(),
49        }
50    }
51
52    pub fn resolve(&self, value: T) -> EventualResolvedFuture<Self> {
53        self.resolve_to_value(value)
54    }
55
56    #[must_use]
57    pub fn take_value(&self) -> Option<T> {
58        let mut inner = self.inner.lock();
59        inner.resolved_value_mut().take()
60    }
61}
62
63pub struct EventualValueFuture<T: Unpin> {
64    id: Option<usize>,
65    eventual: EventualValue<T>,
66}
67
68impl<T: Unpin> core::fmt::Debug for EventualValueFuture<T> {
69    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70        f.debug_struct("EventualValueFuture")
71            .field("id", &self.id)
72            .finish()
73    }
74}
75
76impl<T: Unpin> Future for EventualValueFuture<T> {
77    type Output = EventualValue<T>;
78    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
79        let this = &mut *self;
80        let out = {
81            let mut inner = this.eventual.base_inner();
82            inner.instance_poll(&mut this.id, cx)
83        };
84        match out {
85            None => task::Poll::<Self::Output>::Pending,
86            Some(wakers) => {
87                // Wake all other instance futures
88                for w in wakers {
89                    w.wake();
90                }
91                task::Poll::<Self::Output>::Ready(this.eventual.clone())
92            }
93        }
94    }
95}
96
97impl<T> Drop for EventualValueFuture<T>
98where
99    T: Unpin,
100{
101    fn drop(&mut self) {
102        if let Some(id) = self.id.take() {
103            let wakers = {
104                let mut inner = self.eventual.base_inner();
105                inner.remove_waker(id)
106            };
107            for w in wakers {
108                w.wake();
109            }
110        }
111    }
112}