Skip to main content

ps_promise/methods/shared/promise/implementations/
clone.rs

1use crate::{sync::atomic::Ordering, PromiseRejection};
2
3use super::super::SharedPromise;
4
5impl<T, E> Clone for SharedPromise<T, E>
6where
7    E: PromiseRejection,
8{
9    fn clone(&self) -> Self {
10        Self {
11            state: self.state.clone(),
12            waker: self.waker.clone(),
13            waiter_id: self.state.next_waiter_id.fetch_add(1, Ordering::Relaxed),
14        }
15    }
16}
17
18#[cfg(test)]
19mod tests {
20    use std::{
21        sync::{
22            atomic::{AtomicUsize, Ordering},
23            Arc,
24        },
25        task::{Context, Poll, Waker},
26    };
27
28    use crate::{Promise, PromiseRejection, TaskFailure};
29
30    #[derive(Debug, Clone, PartialEq)]
31    enum E {
32        AlreadyConsumed,
33        Fail,
34        TaskFailed,
35    }
36
37    impl PromiseRejection for E {
38        fn already_consumed() -> Self {
39            Self::AlreadyConsumed
40        }
41
42        fn task_failed(_: TaskFailure) -> Self {
43            Self::TaskFailed
44        }
45    }
46
47    fn cx() -> Context<'static> {
48        Context::from_waker(Waker::noop())
49    }
50
51    fn poll<F: std::future::Future + Unpin>(future: &mut F) -> std::task::Poll<F::Output> {
52        std::pin::Pin::new(future).poll(&mut cx())
53    }
54
55    #[test]
56    fn clone_created_after_settlement_observes_the_result() {
57        let mut shared = Promise::<i32, E>::lazy(async { Ok(11) }).shared();
58
59        assert_eq!(poll(&mut shared), std::task::Poll::Ready(Ok(11)));
60
61        let mut latecomer = shared.clone();
62
63        assert_eq!(poll(&mut latecomer), std::task::Poll::Ready(Ok(11)));
64    }
65
66    #[test]
67    fn many_clones_all_observe_the_result() {
68        let shared = Promise::<i32, E>::lazy(async { Ok(3) }).shared();
69
70        let mut clones: Vec<_> = (0..5).map(|_| shared.clone()).collect();
71
72        for clone in &mut clones {
73            assert_eq!(poll(clone), std::task::Poll::Ready(Ok(3)));
74        }
75    }
76
77    #[test]
78    fn surviving_clone_observes_result_after_others_dropped() {
79        let shared = Promise::<i32, E>::lazy(async { Ok(99) }).shared();
80
81        let extra = shared.clone();
82        let another = shared.clone();
83
84        drop(extra);
85        drop(another);
86
87        let mut survivor = shared;
88
89        assert_eq!(poll(&mut survivor), std::task::Poll::Ready(Ok(99)));
90    }
91
92    #[test]
93    fn two_clones_observe_same_resolved_value() {
94        let shared = Promise::<i32, E>::resolve(42).shared();
95
96        let mut a = shared.clone();
97        let mut b = shared;
98
99        assert_eq!(poll(&mut a), Poll::Ready(Ok(42)));
100        assert_eq!(poll(&mut b), Poll::Ready(Ok(42)));
101    }
102
103    #[test]
104    fn many_clones_observe_same_value() {
105        let shared = Promise::<i32, E>::resolve(7).shared();
106
107        let mut clones: Vec<_> = (0..5).map(|_| shared.clone()).collect();
108
109        for c in &mut clones {
110            assert_eq!(poll(c), Poll::Ready(Ok(7)));
111        }
112    }
113
114    #[test]
115    fn clone_before_and_after_settlement_observe_same_value() {
116        let (promise, resolve, _reject) = Promise::<i32, E>::with_resolvers();
117        let shared = promise.shared();
118
119        let mut early = shared.clone();
120
121        resolve.resolve(99);
122
123        let mut late = shared;
124
125        assert_eq!(poll(&mut early), Poll::Ready(Ok(99)));
126        assert_eq!(poll(&mut late), Poll::Ready(Ok(99)));
127    }
128
129    #[test]
130    fn cloning_does_not_run_inner_computation_more_than_once() {
131        let counter = Arc::new(AtomicUsize::new(0));
132
133        let probe = counter.clone();
134        let shared = Promise::<i32, E>::lazy(async move {
135            probe.fetch_add(1, Ordering::SeqCst);
136            Ok(123)
137        })
138        .shared();
139
140        let mut clones: Vec<_> = (0..4).map(|_| shared.clone()).collect();
141
142        for c in &mut clones {
143            assert_eq!(poll(c), Poll::Ready(Ok(123)));
144        }
145
146        assert_eq!(counter.load(Ordering::SeqCst), 1);
147    }
148
149    #[test]
150    fn dropping_some_clones_does_not_prevent_survivor_observing_result() {
151        let shared = Promise::<i32, E>::resolve(55).shared();
152
153        let mut survivor = shared.clone();
154
155        let doomed_a = shared.clone();
156        let doomed_b = shared.clone();
157
158        drop(doomed_a);
159        drop(doomed_b);
160        drop(shared);
161
162        assert_eq!(poll(&mut survivor), Poll::Ready(Ok(55)));
163    }
164
165    #[test]
166    fn clone_observes_rejection_identically() {
167        let shared = Promise::<i32, E>::lazy(async { Err(E::Fail) }).shared();
168
169        let mut a = shared.clone();
170        let mut b = shared;
171
172        assert_eq!(poll(&mut a), Poll::Ready(Err(E::Fail)));
173        assert_eq!(poll(&mut b), Poll::Ready(Err(E::Fail)));
174    }
175}