Poperton
Poperton

Reputation: 2176

Await on join handle inside async?

I have a video player that plays a stream and should return whenever the video producer, the decoder or the renderer fails

pub async fn play_video(s: &MyStream) -> Result<(), Error> {
    tokio::select! {
        r = s.video_producer.run() => {
            Ok(r?)
        }
        r = s.decoder.run() => {
            Ok(r?)
        }
        //Renderer would go here, but it can't cause it's not `Send`
    }
}

However, since a Renderer usually has to be on a thread and not move to another, it's not Send, so it cannot be used inside an async call.

My solution was to spawn a thread and create the renderer inside the thread, so it never has to be moved from threads:

let renderer_join_handle = std::thread::spawn(move || {
    //...
})

I get a JoinHandle<Result<(),RendererError>> for which I can detect errors and return. However, it's not like the tokio select where it returns immediately. Is there a way to continuously poll this JoinHandle in the tokio select, thus async? Or is there a better solution that I'm not aware?

Basically I wanted the Renderer to be like the video producer and the decoder, and return its error on the tokio select.

Upvotes: 0

Views: 1664

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 71055

Don't use std::thread::spawn(). Use tokio::task::spawn_blocking().

Alternatively, if the rendered must be on its own thread, you can create a oneshot async channel via tokio::sync::oneshot::channel(). send() the result to it from the rendered thread when it is finished, and receive from it by the select!.

Upvotes: 1

Related Questions