genawaiter icon indicating copy to clipboard operation
genawaiter copied to clipboard

Forcing Send on a guard when using genawaiter

Open fabianmurariu opened this issue 1 year ago • 0 comments

This is more of a question rather than an issue, we're using parking_lot with genawaiter to get an iterator without lifetime from a struct.


   use genawaiter::sync::{gen, GenBoxed};
   use genawaiter::yield_;

    struct Example<T>(Arc<parking_lot::RwLock<Vec<T>>>);

    impl<T: Clone> Example<T> {
        fn iter(&self) -> impl Iterator<Item = T> {
            let tgshard = self.0.clone();
            let iter: GenBoxed<T> = GenBoxed::new_boxed(|co| async move {
                let g = tgshard.read();
                let iter = (*g).iter();
                for t in iter {
                    co.yield_(t.clone()).await;
                }
            });

            iter.into_iter()
        }
    }

this is not allowed by the rust compiler because the guard is not Send.

However, is forcing the guard in this scenario (using genawaiter ) to be Send an actual problem? I don't think the guard will be moved onto another thread. (that being said I have no clue how genawaiter works)

Basically is this workable?

   use genawaiter::sync::{gen, GenBoxed};
   use genawaiter::yield_;
   
    struct MyLock<T>(parking_lot::RwLock<T>);
    struct MyGuard<'a, T>(parking_lot::RwLockReadGuard<'a, T>);

    impl<T: Clone> MyLock<T> {
        fn read(&self) -> MyGuard<T> {
            MyGuard(self.0.read())
        }
    }

    impl<T> Deref for MyGuard<'_, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            self.0.deref()
        }
    }

    unsafe impl<T> Send for MyGuard<'_, T> {}

    struct Example2<T>(Arc<MyLock<Vec<T>>>);

    impl<T: Clone + std::marker::Send + std::marker::Sync + 'static> Example2<T> {
        fn iter(&self) -> impl Iterator<Item = T> {
            let tgshard = self.0.clone();
            let iter: GenBoxed<T> = GenBoxed::new_boxed(|co| async move {
                let g = tgshard.read();
                let iter = (*g).iter();
                for t in iter {
                    co.yield_(t.clone()).await;
                }
            });

            iter.into_iter()
        }
    }

fabianmurariu avatar Mar 08 '23 10:03 fabianmurariu