genawaiter/sync/boxed.rs
1use crate::sync::{Co, Gen};
2use std::{future::Future, pin::Pin};
3
4/// This is a type alias for generators which can be stored in a `'static`. It's
5/// only really needed to help the compiler's type inference along.
6#[allow(clippy::module_name_repetitions)]
7pub type GenBoxed<Y, R = (), C = ()> =
8 Gen<Y, R, Pin<Box<dyn Future<Output = C> + Send>>>;
9
10impl<Y, R, C> GenBoxed<Y, R, C> {
11 /// Creates a new generator with a boxed future, so it can be stored in a
12 /// `static`.
13 ///
14 /// This works exactly the same as [`Gen::new`](struct.Gen.html#method.new)
15 /// with an immediately boxed future.
16 ///
17 /// This method exists solely to help the compiler with type inference.
18 /// These two lines are equivalent, except that the compiler cannot infer
19 /// the correct type on the second line:
20 ///
21 /// ```compile_fail
22 /// # use genawaiter::sync::{Co, Gen, GenBoxed};
23 /// # use std::{future::Future, pin::Pin};
24 /// #
25 /// # async fn producer(co: Co<i32>) {
26 /// # for n in (1..).step_by(2).take_while(|&n| n < 10) { co.yield_(n).await; }
27 /// # }
28 /// #
29 /// let _: GenBoxed<i32> = Gen::new_boxed(|co| producer(co));
30 /// let _: GenBoxed<i32> = Gen::new(|co| Box::pin(producer(co)));
31 /// ```
32 pub fn new_boxed<F>(producer: impl FnOnce(Co<Y, R>) -> F) -> Self
33 where
34 F: Future<Output = C> + Send + 'static,
35 {
36 Self::new(|co| Box::pin(producer(co)))
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use crate::{
43 ops::GeneratorState,
44 sync::{Co, Gen},
45 };
46 use std::sync::{Arc, Mutex};
47
48 async fn odd_numbers_less_than_ten(co: Co<i32>) {
49 for n in (1..).step_by(2).take_while(|&n| n < 10) {
50 co.yield_(n).await;
51 }
52 }
53
54 #[test]
55 fn can_be_stored_in_static() {
56 let gen = Gen::new_boxed(odd_numbers_less_than_ten);
57
58 // `T` must be `Send` for `Mutex<T>` to be `Send + Sync`.
59 let _: &dyn Send = &gen;
60
61 let arc = Arc::new(Mutex::new(gen));
62
63 // A type must be `Sync` to be stored in a `static`. (In this particular case,
64 // this is the case for `Arc<Mutex<T>>` if `Gen<...>` is `Send`.
65 let _: &dyn Sync = &arc;
66
67 let mut guard = arc.lock().unwrap();
68 assert_eq!(guard.resume(), GeneratorState::Yielded(1));
69 assert_eq!(guard.resume(), GeneratorState::Yielded(3));
70 }
71}