How to run async in crossbeam scope?

Hello,

I have an async function as follows which makes use of crossbeam thread scope:

use crossbeam_utils::thread;
use core_lib::request;

 pub async fn test(){
    // Will perform stuff here
    println!("will perform stuff here");
 }

 pub async fn initiate(){
    

    if let Ok(result) = request::Request::get_request().await{
        let message = result.message().iter();
        thread::scope(|s| {
            for r in message{
                log::debug!("Detected request id: {}",r.id());
                println!("{:?}",r.config());

                s.spawn(move |_| {
                    
                    log::info!("Processing request id: {}", r.id());
                    test().await;
                });

            }
        }).unwrap_or_default();
    }
}

If I compile this I get the following error:

 |
36 |                 s.spawn(move |_| {
   |                         -------- this is not `async`
...
48 |                     test().await;
   |                     ^^^^^^^^^^^^ only allowed inside `async` functions and blocks

I tried to add async in the spawn as such but this block is never executed:

s.spawn(move |_| async move{
     log::info!("Processing request id: {}", r.id());
     test().await;
});

How do I execute my async test function in the s.spawn ? Any help would be appreciable. Thanks

You can't do this, even if you don't .await anything inside the scope because the thread::scope method blocks the thread.

1 Like

Thanks for the info. Sorry am new to rust async.

I was using tokio::spawn initially with which the I can call my test().await

.......
    if let Ok(result) = request::Request::get_request().await{
        let message = result.message().iter();
            for req in message{
                log::debug!("Detected request id: {}",req.id());
                println!("{:?}",req.config());
                tokio::spawn(async move{
                    println!("Processing request id: {}",req.id());
                    test().await;
               });
        }
 }


However, am getting a lifetime issue:

19 |         let message = result.message().iter();
   |                       ^^^^^^----------
   |                       |
   |                       borrowed value does not live long enough
   |                       argument requires that `result` is borrowed for `'static`
...
58 |     }
   |     - `result` dropped here while still borrowed

Thats why I used crossbeam scope to prevent this issue. Any suggestions would be appreciable thanks

Unfortunately there is no asynchronous equivalent to scoped threads. You have to take ownership of the value in some way to move it into the task. Usually you do this by either calling a method like into_iter() rather than iter() or by cloning, but as I don't know what the types involved are, I can't tell you which of these apply to your situation.

1 Like

Thanks for your reply :grinning:

The result.message() is of type Vec

Please find below the struct

#[derive(Debug,Getters,Deserialize,Serialize)]
pub struct Request{
    status: String,
    message: Vec<RequestData>
}


#[derive(Debug,Getters,Deserialize,Serialize)]
pub struct  RequestData{
   id: i64,
   config: String,
   title: String,
   valid: bool,
   status: String,
   meta: String,
}

What does message() return? Does it return a vector, or a reference to a vector?

It returns a reference: &Vec<RequestData>

Then you would have to clone the RequestData before spawning. The only way to avoid the clone is to take ownership of the data in the vector, which you can't do through an immutable reference.

I will note that returning &Vec<T> is unidiomatic. The type &[T] is preferred.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.