rmanoka / async-scoped

A scope for async_std and tokio to spawn non-static futures
117 stars 14 forks source link

Return result containing references #11

Closed SetheenDev closed 2 years ago

SetheenDev commented 2 years ago

Hello! I'd like to use this library but cannot figure out how to return references. This is the equivalent using raw crossbeam:

fn main(){
    let group1 = [1,2,3];
    let group2 = [4,5,6];
    let groups = [group1, group2];
    let results = crossbeam::scope(|s| {
        let mut results = Vec::<&i32>::new();
        let mut handles = vec![];
        for group in &groups {
            handles.push(s.spawn(move |_| {
                &group[0]
            }));
        }
        for handle in handles {
            results.push(handle.join().unwrap());
        }
        results
    });

    println!("{:?}", results.unwrap());
}

playground example

Using the async version, "&groups does not live long enough":

let group1 = [1,2,3];
let group2 = [4,5,6];
let groups = [group1, group2];
let results = async_scoped::TokioScope::scope_and_block(|s| {
    for group in &groups {
        s.spawn(async {
            &group[0]
        });
    }
});

Same with _scope_andcollect. I don't think this is a bug, I'm new to rust and could use a pointer if this is possible. Thanks!

rmanoka commented 2 years ago

Nice catch @SetheenDev ! crossbeam uses some sync. mechanisms to store the returned objects, that our design does not do. This causes a restriction on the output of the future being 'static. We could try to implement the crossbeam-style mechanism too, but I don't know how big a change it is / how it might affect performance.

For now, you could use sync. mechanisms like oneshot or mpsc channels of the tokio or futures crates. It is a bit more verbose, but should get around the lifetime issues.

SetheenDev commented 2 years ago

Thanks for responding @rmanoka. I didn't think about oneshot but that seems perfect! Thank you!