Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is required to implement Send and Sync? #185

Open
J-Cake opened this issue Oct 28, 2022 · 2 comments
Open

What is required to implement Send and Sync? #185

J-Cake opened this issue Oct 28, 2022 · 2 comments

Comments

@J-Cake
Copy link

J-Cake commented Oct 28, 2022

In the process of integrating Raqote into several lower-level projects involving frame buffers and DRM etc, I'm looking into multithreadded applications, and noticed that DrawTargets don't seem to support this.

NonNull<raqote::rasterizer::ActiveEdge> cannot be sent between threads safely.

I'm wondering what's involved in order to achieve thread-safety, such as locking a mutex before rasterisation etc, as well as whether there are plans for this?

Thanks heaps. Love the library.

@wchargin
Copy link

I'm also a bit puzzled by this, but I got around it by just sending the
width, height, and underlying buffer around. Naturally, this loses the
other bits of state on a DrawTarget (layers, clips, transforms), but
if you're just trying to pass around the image data then it works fine:

use std::sync::{Arc, Mutex};

struct Output {
    i: u32,
    // `DrawTarget` is `!Send`, so we break it down into its components.
    width: i32,
    height: i32,
    data: Vec<u32>,
}
let outputs = Arc::new(Mutex::new(Vec::<Output>::new()));

std::thread::scope(|s| {
    for i in 0..steps {
        let outputs = outputs.clone();
        s.spawn(move || {
            let mut dt = DrawTarget::new(...);
            // ... paint onto `dt` (expensive) ...
            let output = Output {
                i,
                width: dt.width(),
                height: dt.height(),
                data: dt.into_inner(),
            };
            // lock the mutex just briefly to push our results
            outputs.lock().expect("poison").push(output);
        });
    }
});

let mut composite = DrawTarget::new(...);
for output in outputs.lock().expect("poison").iter() {
    let img = raqote::Image {
        width: output.width,
        height: output.height,
        data: output.data.as_slice(),
    };
    composite.draw_image_at(some_x, some_y, &img, DrawOptions::new());
}

@geniusnut
Copy link

My work-around is using the SendWrapper to wrap the font in a static parameter.

use font_kit::font::Font;
use send_wrapper::SendWrapper;
lazy_static! {
    pub static ref RES_FONT_ID_MAP: Mutex<HashMap<String, SendWrapper<Font>>> = {
        let m = HashMap::new();
        Mutex::new(m)
    };
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants