Forcing Send on a guard when using genawaiter
fabianmurariu opened this issue · 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.
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?
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()
}
}
You are using genawaiter::sync::GenBoxed
which is explicitly meant for the case where the generator will be sent across threads AFAICT. Try using genawaiter::rc::Gen
instead which doesn't require Send
.
Thanks for the help