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}