1use core::future::Future;
10use core::pin::Pin;
11use core::sync::atomic::{AtomicBool, AtomicI64, Ordering};
12use core::time::Duration;
13use std::sync::Arc;
14
15#[cfg(not(target_arch = "wasm32"))]
17pub trait MaybeSend: Send {}
18#[cfg(not(target_arch = "wasm32"))]
19impl<T: Send + ?Sized> MaybeSend for T {}
20
21#[cfg(target_arch = "wasm32")]
23pub trait MaybeSend {}
24#[cfg(target_arch = "wasm32")]
25impl<T: ?Sized> MaybeSend for T {}
26
27#[cfg(not(target_arch = "wasm32"))]
29pub trait MaybeSync: Sync {}
30#[cfg(not(target_arch = "wasm32"))]
31impl<T: Sync + ?Sized> MaybeSync for T {}
32
33#[cfg(target_arch = "wasm32")]
35pub trait MaybeSync {}
36#[cfg(target_arch = "wasm32")]
37impl<T: ?Sized> MaybeSync for T {}
38
39#[cfg(not(target_arch = "wasm32"))]
41pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
42#[cfg(target_arch = "wasm32")]
44pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
45
46#[cfg(not(target_arch = "wasm32"))]
48pub type BoxStream<'a, T> = Pin<Box<dyn futures_core::Stream<Item = T> + Send + 'a>>;
49#[cfg(target_arch = "wasm32")]
51pub type BoxStream<'a, T> = Pin<Box<dyn futures_core::Stream<Item = T> + 'a>>;
52
53pub trait Clock: MaybeSend + MaybeSync {
60 fn now_ms(&self) -> i64;
62}
63
64#[cfg(not(target_arch = "wasm32"))]
66#[derive(Debug, Default, Clone, Copy)]
67pub struct SystemClock;
68
69#[cfg(not(target_arch = "wasm32"))]
70impl Clock for SystemClock {
71 fn now_ms(&self) -> i64 {
72 use std::time::{SystemTime, UNIX_EPOCH};
73 match SystemTime::now().duration_since(UNIX_EPOCH) {
76 Ok(since) => i64::try_from(since.as_millis()).unwrap_or(i64::MAX),
77 Err(before) => i64::try_from(before.duration().as_millis()).map_or(i64::MIN, |ms| -ms),
78 }
79 }
80}
81
82#[derive(Debug, Default)]
85pub struct ManualClock {
86 now_ms: AtomicI64,
87}
88
89impl ManualClock {
90 #[must_use]
92 pub const fn new(start_ms: i64) -> Self {
93 Self {
94 now_ms: AtomicI64::new(start_ms),
95 }
96 }
97
98 pub fn set(&self, now_ms: i64) {
100 self.now_ms.store(now_ms, Ordering::SeqCst);
101 }
102
103 pub fn advance(&self, delta_ms: i64) {
105 self.now_ms.fetch_add(delta_ms, Ordering::SeqCst);
106 }
107}
108
109impl Clock for ManualClock {
110 fn now_ms(&self) -> i64 {
111 self.now_ms.load(Ordering::SeqCst)
112 }
113}
114
115pub trait Spawner: MaybeSend + MaybeSync {
118 fn spawn(&self, fut: BoxFuture<'static, ()>);
120}
121
122pub trait Sleep: MaybeSend + MaybeSync {
127 fn sleep(&self, duration: Duration) -> BoxFuture<'static, ()>;
129}
130
131impl<T: Sleep + ?Sized> Sleep for Arc<T> {
132 fn sleep(&self, duration: Duration) -> BoxFuture<'static, ()> {
133 (**self).sleep(duration)
134 }
135}
136
137#[derive(Debug, Clone, Copy, PartialEq, Eq)]
139pub struct Elapsed;
140
141pub async fn with_timeout<S, F>(sleep: &S, after: Duration, fut: F) -> Result<F::Output, Elapsed>
148where
149 S: Sleep + ?Sized,
150 F: Future,
151{
152 let fut = core::pin::pin!(fut);
153 match futures::future::select(fut, sleep.sleep(after)).await {
154 futures::future::Either::Left((output, _)) => Ok(output),
155 futures::future::Either::Right(((), _)) => Err(Elapsed),
156 }
157}
158
159#[derive(Debug, Clone, Default)]
162pub struct ManualSleep {
163 fired: Arc<AtomicBool>,
164 wake: Arc<tokio::sync::Notify>,
165 requested: Arc<std::sync::Mutex<Vec<Duration>>>,
166}
167
168impl ManualSleep {
169 #[must_use]
171 pub fn new() -> Self {
172 Self::default()
173 }
174
175 #[must_use]
177 pub fn elapsed() -> Self {
178 let sleeper = Self::default();
179 sleeper.fire();
180 sleeper
181 }
182
183 #[must_use]
185 pub fn requested(&self) -> Vec<Duration> {
186 self.requested
187 .lock()
188 .map_or_else(|poisoned| poisoned.into_inner().clone(), |v| v.clone())
189 }
190
191 pub fn fire(&self) {
193 self.fired.store(true, Ordering::SeqCst);
194 self.wake.notify_waiters();
195 }
196}
197
198impl Sleep for ManualSleep {
199 fn sleep(&self, duration: Duration) -> BoxFuture<'static, ()> {
200 match self.requested.lock() {
201 Ok(mut requested) => requested.push(duration),
202 Err(poisoned) => poisoned.into_inner().push(duration),
203 }
204 let (fired, wake) = (self.fired.clone(), self.wake.clone());
205 Box::pin(async move {
206 loop {
207 let notified = wake.notified();
208 if fired.load(Ordering::SeqCst) {
209 return;
210 }
211 notified.await;
212 }
213 })
214 }
215}
216
217#[cfg(not(target_arch = "wasm32"))]
221#[must_use]
222pub fn send_wrap<F: Future + Send>(f: F) -> F {
223 f
224}
225
226#[cfg(target_arch = "wasm32")]
237#[must_use]
238pub fn send_wrap<F: Future>(f: F) -> send_wrapper::SendWrapper<F> {
239 send_wrapper::SendWrapper::new(f)
240}
241
242#[cfg(all(feature = "connect", not(target_arch = "wasm32")))]
246pub(crate) fn send_wrap_stream<S: futures_core::Stream + Send>(s: S) -> S {
247 s
248}
249
250#[cfg(all(feature = "connect", target_arch = "wasm32"))]
253pub(crate) fn send_wrap_stream<S: futures_core::Stream>(s: S) -> send_wrapper::SendWrapper<S> {
254 send_wrapper::SendWrapper::new(s)
255}
256
257#[cfg(all(test, not(target_arch = "wasm32")))]
259mod tests {
260 use super::*;
261
262 #[test]
263 fn manual_clock_advances() {
264 let clock = ManualClock::new(1_000);
265 assert_eq!(clock.now_ms(), 1_000);
266 clock.advance(250);
267 assert_eq!(clock.now_ms(), 1_250);
268 clock.set(7);
269 assert_eq!(clock.now_ms(), 7);
270 assert_eq!(ManualClock::default().now_ms(), 0);
271 }
272
273 #[test]
274 fn system_clock_is_after_2020() {
275 assert!(SystemClock.now_ms() > 1_577_836_800_000);
277 }
278
279 #[test]
280 fn send_wrap_is_identity_on_native() {
281 let fut = send_wrap(async { 41 + 1 });
282 assert_eq!(futures_executor::block_on(fut), 42);
283 }
284
285 fn assert_send<T: Send>(_: &T) {}
286
287 trait Service {
289 fn call(&self) -> impl Future<Output = u8> + MaybeSend;
290 }
291
292 struct Seven;
293 impl Service for Seven {
294 async fn call(&self) -> u8 {
295 7
296 }
297 }
298
299 fn require_send_from_generic<S: Service>(service: &S) -> u8 {
303 let fut = service.call();
304 assert_send(&fut);
305 futures_executor::block_on(fut)
306 }
307
308 #[test]
309 fn maybe_send_future_is_send_to_generic_callers_on_native() {
310 assert_eq!(require_send_from_generic(&Seven), 7);
311 let boxed: BoxFuture<'static, u8> = Box::pin(Seven.call());
312 assert_send(&boxed);
313 }
314
315 #[test]
316 fn with_timeout_returns_a_ready_future_and_times_out_a_pending_one() {
317 let never = ManualSleep::new();
318 let ready = with_timeout(&never, Duration::from_secs(5), async { 9 });
319 assert_eq!(futures_executor::block_on(ready), Ok(9));
320 let fired = ManualSleep::elapsed();
321 let stuck = with_timeout(
322 &fired,
323 Duration::from_secs(5),
324 core::future::pending::<u8>(),
325 );
326 assert_eq!(futures_executor::block_on(stuck), Err(Elapsed));
327 let both = with_timeout(&fired, Duration::from_secs(5), async { 3 });
329 assert_eq!(futures_executor::block_on(both), Ok(3));
330 }
331
332 #[test]
333 fn manual_sleep_wakes_a_pending_sleep_when_fired() {
334 let sleeper = ManualSleep::new();
335 let timer = sleeper.sleep(Duration::from_secs(1));
336 let woken = std::sync::Arc::new(core::sync::atomic::AtomicBool::new(false));
337 let flag = woken.clone();
338 let handle = std::thread::spawn(move || {
339 futures_executor::block_on(timer);
340 flag.store(true, Ordering::SeqCst);
341 });
342 std::thread::sleep(Duration::from_millis(50));
343 assert!(!woken.load(Ordering::SeqCst));
344 sleeper.fire();
345 handle.join().unwrap();
346 assert!(woken.load(Ordering::SeqCst));
347 }
348
349 #[test]
350 fn spawner_accepts_boxed_futures() {
351 struct Inline;
352 impl Spawner for Inline {
353 fn spawn(&self, fut: BoxFuture<'static, ()>) {
354 futures_executor::block_on(fut);
355 }
356 }
357 let ran = std::sync::Arc::new(core::sync::atomic::AtomicBool::new(false));
358 let flag = ran.clone();
359 Inline.spawn(Box::pin(async move { flag.store(true, Ordering::SeqCst) }));
360 assert!(ran.load(Ordering::SeqCst));
361 }
362}