rustreference-counting

Is it possible to access a variable from the enclosing scope inside a callback function in Rust without reference counting or mutexes?


I am an absolute beginner with rust, so apologies if my question is not phrased in the correct terms, I am happy to provide more clarification if needed.

I am writing a program using sdl and rlua. This program will load and run a lua script, and provide functions that the script can use. These functions will enable drawing to the SDL renderer.

In order to do that, the rust functions that I register with lua need to have access to the SDL renderer (or canvas as it is called by this SDL wrapper).

The only way I have found to access canvas in my lua callback is to wrap it in a reference counted mutex. This allows me to maintain multiple mutable references to it, so I can continue to access it in the rest of the enclosing scope. Here is a stripped back version of what I have:

extern crate rlua;
extern crate sdl2;

use std::rc::Rc;
use std::sync::Mutex;

fn main() {
    let lua = rlua::Lua::new();

    let sdl = sdl2::init().unwrap();
    let video = sdl.video().unwrap();

    let window = video.window("", 640, 320).resizable().build().unwrap();

    let canvas = Rc::new(Mutex::new(window.into_canvas().build().unwrap()));
    
    let draw_rect_canvas = canvas.clone();
    let draw_rect = lua
        .create_function_mut(move |_, (x, y, w, h): (i32, i32, u32, u32)| {
            draw_rect_canvas
                .lock()
                .unwrap()
                .draw_rect(sdl2::rect::Rect::new(x, y, w, h))
                .unwrap();
            Ok(())
        })
        .unwrap();

    lua.globals().set("draw_rect", draw_rect).unwrap();

    canvas
        .lock()
        .unwrap()
        .set_draw_color(sdl2::pixels::Color::RGB(0, 0, 0));
}

This compiles, and does what I need it to. However, I am left wondering if either the reference counting or mutex are really necessary here, as I assume they introduce a small runtime overhead.

Is there any other way I can tell the compiler the following?


Solution

  • Reference counting and interior mutability look like the correct call here, but you should definitely replace Mutex with RefCell, for better performance and debuggability.

    If you have had only one function that needs access to the canvas and no need to access it in the main function, you could've move it directly into the closure without Rc<RefCell>, but it looks like this isn't the case.