Search code examples
multithreadingrustinfinite-loop

Run 3 async task indepedently in infinite loop


I have 3 different async methods say func1, func2, func3 on a struct object.

What I want to accomplish is something like:

loop {
    obj.func1().await;
    set_timeout(Duration::from_secs(5)).await;
}

loop {
    obj.func2().await;
    set_timeout(Duration::from_secs(5)).await;
}

loop {
    obj.func3().await;
    set_timeout(Duration::from_secs(5)).await;
}

I want all these 3 loops to run in parallel. Obviously, in this form it won't work because the 2nd and 3rd loops will be unreachable.

I've thought of the below solution:

loop {
    thread::spawn(move || async move {
        obj.func1().await;
        obj.func2().await;
        obj.func3().await;
        set_timeout(Duration::from_secs(5)).await;
    });
}

But it has 2 issues:

  1. My struct does not implement the Copy trait (using some 3rd party crates, so cannot do much there).
  2. As every function call will run as a seperate thread here, I doubt the timeout will work properly here!

How should I approach this?


Solution

  • You can use an async block to create a new future, so if you wrap each loop in an async block you'll get three futures. Then you can use the join! macro to await them all simultaneously:

    let fut1 = async {
        loop {
            obj.func1().await;
            set_timeout(Duration::from_secs(5)).await;
        }
    };
    
    let fut2 = async {
        loop {
            obj.func2().await;
            set_timeout(Duration::from_secs(5)).await;
        }
    };
    
    let fut3 = async {
        loop {
            obj.func3().await;
            set_timeout(Duration::from_secs(5)).await;
        }
    };
    
    join!(fut1, fut2, fut3);
    

    The join! macro will drive the futures.

    Alternatively, your async runtime likely has a way to submit a future as a new independent task, such as tokio::spawn.