#Errors while putting a sender into a closure

12 messages · Page 1 of 1 (latest)

quartz imp
#

So I'm trying to implement multithreading in my application that generates images.
I generate a vector of closures, each of which generates one image. Then I create some threads and divide the work between the threads.
The code looks like that:

let (sender, receiver) = std::sync::mpsc::channel::<(usize, Image)>();
.
.
.
if ui.button("start").clicked() {
	let mut images: Vec<Artpiece> = Vec::with_capacity(*batch_size);

	let mut jobs: Vec<Box<dyn Fn() + Send + Sync + 'static>> = Vec::with_capacity(*batch_size);

	for i in 0..*batch_size {
		let artpiece = Artpiece::new(
			Expression::random(*initial_complexity), 
			Expression::random(*initial_complexity), 
			Expression::random(*initial_complexity),
			*resolution
		);


		let size_clone = resolution as u32;
		let sender_clone = sender.clone();
		let r_exp_clone = artpiece.expression_red.clone();
		let g_exp_clone = artpiece.expression_green.clone();
		let b_exp_clone = artpiece.expression_blue.clone();
		
		jobs.push(Box::new(move || {
			let mut img = Image::gen_image_color(size_clone as u16, size_clone as u16, color_u8!(50, 50, 50, 255));
			for x in 0..size_clone {
				for y in 0..size_clone {
					// calculations omitted 
				}
			}

			sender_clone.send((i, img)).unwrap();
		}));

		
		images.push(artpiece);
	}

	let thread_num = 10;
	let jobs_per_thread = jobs.len() as f32 / thread_num as f32;
	
	let mut i = 0f32;
	for _ in 0..thread_num {
		let start = i as usize;
		let end = (i + jobs_per_thread) as usize;
		i += jobs_per_thread;
		
		let jobs_slice = jobs.drain(start..end).collect::<Vec<_>>();

		std::thread::spawn(move || {
			for job in &jobs_slice[start..end] {
				job();
			}
		});
	}
}

In different place in code the receiver reads the messages and displays them.
The problem is, the compiler doesn't like me putting senders in closures that aren't defined inside thread::spawn
I'll put the error message below due to length limit.

#

the error message:

error[E0277]: `Sender<(usize, macroquad::texture::Image)>` cannot be shared between threads safely
   --> src\main.rs:137:20
    |
137 |    ...                   jobs.push(Box::new(move || {
    |  __________________________________^________-
    | | _________________________________|
    | ||
138 | || ...                       let mut img = Image::gen_image_color(size_clone as u16, size_clone as u16, color_u8!(50, 50, 50, 255));
139 | || ...                       for x in 0..size_clone {
140 | || ...                           for y in 0..size_clone {
...   ||
152 | || ...                       sender_clone.send((i, img)).unwrap();
153 | || ...                   }));
    | ||_______________________-^ `Sender<(usize, macroquad::texture::Image)>` cannot be shared between threads safely
    | |________________________|
    |                          within this `[closure@src\main.rs:137:29: 153:11]`
    |
    = help: within `[closure@src\main.rs:137:29: 153:11]`, the trait `Sync` is not implemented for `Sender<(usize, macroquad::texture::Image)>`
    = note: required because it appears within the type `[closure@src\main.rs:137:29: 153:11]`
    = note: required for the cast to the object type `dyn Fn() + Send + Sync`
quartz imp
#

Now I'm trying to convert images to Arc<Mutex<Vec<>>>, instead of using sending

crimson walrus
inland nimbus
#

a really easy way to do this would be to use

nocturne islandBOT
#

Simple work-stealing parallelism for Rust

Version

1.5.3

Downloads

32 397 843

inland nimbus
#

which's implementation is probably a lot better