How to pass struct to other function that use tokio without Copy trait

Hello,
I want to pass a struct config inside a function with tokio::spawn but since it doesnt implements Copy trait it's not working...
The vectors are created from arguments so I can't make them fixed arrays
Can you help me please ? I'm stuck on it, I also tried to pass as references but I didnt find a way to make it work...
Here is something that replicate my code:

struct Urlconfig {
    whitelist: Vec<String>,
    whitelist_code: Vec<u16>,
}

async fn run_one(config: Urlconfig){
    println!("run One");
    let configClone = config.clone();
    let mut join_handles = Vec::with_capacity(2);
    join_handles.push(tokio::spawn(async move{
            run_two(configClone)
    }));
    for handle in join_handles {
        let ret = handle.await;
    }
        
}
async fn run_two(config: Urlconfig) -> usize{
    println!("run two");
    println!("{}",config.whitelist[0]);
    return 1;
}

fn main() {



    let numbers: Vec<u16> = vec![1, 2, 3, 4, 5];
    let strings: Vec<String> = vec!["one".to_string(), "two".to_string()];


    let config = Urlconfig {
        whitelist: strings,
        whitelist_code: numbers
    };

    run_one(config);
}

you are the right track. you just need to implement Clone for the struct, which can be done using #[derive(Clone)] attribute, like so:

#[derive(Clone)]
struct Urlconfig {
    whitelist: Vec<String>,
    whitelist_code: Vec<u16>,
}

tokio::spawn() requires the future to be 'static, so in general you cannot use reference here (unless you make it 'static, that is). this config data doesn't take much space, just clone and pass by value is totally fine.

Thank you @nerditation but sorry I think my code is not exactly the same because I tried that on my real code and got an error,
Here is the code that replicate the error:


#[tokio::main]
async fn main() {
        
    let numbers: Vec<u16> = vec![1, 2, 3, 4, 5];
    let strings: Vec<String> = vec!["one".to_string(), "two".to_string()];
    let domains: Vec<String> = vec!["google.com".to_string(), "amazon.com".to_string()];


    let config = UrlConfig {
       subs: true,
       whitelist_code: numbers,
       blacklist: strings
    };

    run_urls(domains,config)
    .await;
}


#[derive(Clone)]
struct UrlConfig {
    subs: bool,
    blacklist: Vec<String>,
    whitelist_code: Vec<u16>,
}


async fn run_urls(domains: Vec<String>, config: UrlConfig) {
    let mut join_handles = Vec::with_capacity(domains.len());
    let configClone = config.clone();
    for domain in domains {
        join_handles.push(tokio::spawn(async move{
            run_url(domain, configClone) }))};

    let mut output_string = String::new();
    for handle in join_handles {
        let ret_url = handle.await.expect("fail");
        output_string.push_str(ret_url.await.as_str());
    }
    
}

async fn run_url(domain: String,config: UrlConfig) -> String {
    let pattern = if config.subs {
        format!("*.{}%2F*", domain)
    } else {
        format!("{}%2F*", domain)
    };
    return pattern
}

and the error i get is :

error[E0382]: use of moved value: `configClone`
  --> src/main.rs:33:40
   |
31 |       let configClone = config.clone();
   |           ----------- move occurs because `configClone` has type `UrlConfig`, which does not implement the `Copy` trait
32 |       for domain in domains {
   |       --------------------- inside of this loop
33 |           join_handles.push(tokio::spawn(async move{
   |  ________________________________________^
34 | |             run_url(domain, configClone) }))};
   | |_____________________________-----------__^ value moved here, in previous iteration of loop
   |                               |
   |                               use occurs due to use in generator
   |
help: consider cloning the value if the performance cost is acceptable
   |
34 |             run_url(domain, configClone) }.clone()))};
   |                                           ++++++++

For more information about this error, try `rustc --explain E0382`.
error: could not compile `playground` (bin "playground") due to previous error

Sorry for the mistake,I'm not sure why this errror happens it doesnt look so different

You have to clone it once for every single call to tokio::spawn. And you must call .clone() before the call to tokio::spawn. So you want this:

for domain in domains {
    let configClone = config.clone();
    join_handles.push(tokio::spawn(async move { run_url(domain, configClone) }))
}

Putting the call to clone inside the for loop ensures that you make the right number of clones.

@alice Thank you it works like that !

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.