Spawn long-running, interactive thread in struct?


#1

I am experimenting with a multi-threaded program that includes a render thread (with something like glium, for example). I am currently trying to architect it like this:

pub struct RenderEngine {
    meshes: Vec<RenderMesh>,
}

impl RenderEngine {
    pub fn new() -> RenderEngine {
        RenderEngine { meshes: Vec::new() }
    }

    // draw functions here

    pub fn render(&mut self) {
        thread::spawn(move || {
            let display = ...; // glium stuff
            loop {
                let target = display.draw();
                for mesh in &self.meshes {
                    self.draw_mesh(display, &mut target, mesh);
                }
        });
    }
}

fn main() {
    let render_engine = RenderEngine::new();
    render_engine.render();
    // some control loop here
}

However, I get the “self does not fulfill the required lifetime [E0477]” error because the RenderEngine might die before the spawned thread terminates.

I want to be able to have a render thread, that I can give thread-safe (Send/Sync) references to other objects, and that I can communicate to in order to add meshes, change properties, get properties, etc. Is there an example of a good way to design this kind of system that satisfies Rust’s ownership model? Am I on the right track and just need to make a change around where I am starting the thread? How should I start the thread and give it the RenderEngine?

Thanks in advance!


#2

There is no such thing as “thread safe reference”. Thread and any object outside of it have their own lifetimes.
Your choices are:

  1. Send the object (not reference) to the thread.
  2. Scoped thread that will guarantee that thread will not outlive your data:
    See https://aturon.github.io/crossbeam-doc/crossbeam/struct.Scope.html
  3. “I know better” unsafe (but no human really does).

However generally this is bad idea. Get the threading out of the struct and make it responsibility of whoever will use it.