ps_promise/methods/shared/promise/implementations/
clone.rs1use 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}