fail: Threads want full ownership, do another way

Saving for reference more than anything. The threads take ownership of
the data (the closures do, but whatever). Moving the return channel out
of the dispatcher means the dispatcher can't be moved into the feeder
thread.

I see a few solutions from here:
1. Proxy the return channel with another channel. Give the whole
   dispatcher to the feeder thread and hook up another output channel.
   Have the feeder unload the return and pass it through.
2. Rewrite the dispatcher constructor to pass a tuple of the dispatcher
   minus it's return channel, and the return channel now as a separate
   object. This could let them have independent lifetimes and then I can
   pass them around like I'm trying to do.
3. Have main do all the job feeding, result unloading, and
   recompositing. Don't have a feeder and collector thread, and just
   have main bounce between loading a few, and unloading a few.
This commit is contained in:
2023-06-25 09:00:47 -05:00
parent a4a389c10d
commit 65185c7996
2 changed files with 31 additions and 21 deletions

View File

@@ -18,6 +18,8 @@ use rand::{Rng, SeedableRng};
use rand::rngs::SmallRng;
use rand::distributions::Uniform;
use std::thread;
fn main() {
// image
let aspect_ratio = 3.0 / 2.0;
@@ -62,29 +64,37 @@ fn main() {
samples_per_pixel,
world,
};
let mut dispatcher = thread_utils::Dispatcher::new(&small_rng);
for y in (0..image.1).rev() {
eprintln!("Submitting scanline: {}", y);
let job = RenderCommand::Line { line_num: y, context: context.clone() };
dispatcher.submit_job(job);
}
//TODO: Dispatcher shutdown mechanism
// Just gonna take advantage of the round-robin dispatching to
// get a stop command to each thread
dispatcher.submit_job(RenderCommand::Stop);
dispatcher.submit_job(RenderCommand::Stop);
dispatcher.submit_job(RenderCommand::Stop);
dispatcher.submit_job(RenderCommand::Stop);
// ... also I happen to know there are 4 threads.
thread::scope(|s| {
let mut dispatcher = thread_utils::Dispatcher::new(&small_rng);
let scanline_receiver = dispatcher.render_rx;
while let Ok(scanline) = dispatcher.render_rx.recv() {
//TODO: sort results once multiple threads are introduced.
eprintln!("Received scanline: {}", scanline.line_num);
for color in scanline.line {
println!("{}", color.print_ppm(samples_per_pixel));
s.spawn(move || {
for y in (0..image.1).rev() {
eprintln!("Submitting scanline: {}", y);
let job = RenderCommand::Line { line_num: y, context: context.clone() };
dispatcher.submit_job(job);
}
//TODO: Dispatcher shutdown mechanism
// Just gonna take advantage of the round-robin dispatching to
// get a stop command to each thread
dispatcher.submit_job(RenderCommand::Stop);
dispatcher.submit_job(RenderCommand::Stop);
dispatcher.submit_job(RenderCommand::Stop);
dispatcher.submit_job(RenderCommand::Stop);
// ... also I happen to know there are 4 threads.
});
eprintln!("Reached the scanline collector");
while let Ok(scanline) = scanline_receiver.recv() {
//TODO: sort results once multiple threads are introduced.
eprintln!("Received scanline: {}", scanline.line_num);
for color in scanline.line {
println!("{}", color.print_ppm(samples_per_pixel));
}
}
}
});
// TODO: Dispatcher shutdown mechanism. Right now, we might technically be leaking threads.
eprintln!("Done!");
}