RosettaCodeData/Task/Synchronous-concurrency/Rust/synchronous-concurrency.rust

72 lines
2.1 KiB
Plaintext

use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::sync::mpsc::{channel, sync_channel};
use std::thread;
fn main() {
// The reader sends lines to the writer via an async channel, so the reader is never blocked.
let (reader_send, writer_recv) = channel();
// The writer sends the final count via a blocking channel with bound 0,
// meaning the buffer is exactly the size of the result.
let (writer_send, reader_recv) = sync_channel(0);
// Define the work the reader will do.
let reader_work = move || {
let file = File::open("input.txt").expect("Failed to open input.txt");
let reader = BufReader::new(file);
for line in reader.lines() {
match line {
Ok(msg) => reader_send
.send(msg)
.expect("Failed to send via the channel"),
Err(e) => println!("{}", e),
}
}
// Dropping the sender disconnects it and tells the receiver the connection is closed.
drop(reader_send);
// Now that we've sent all the lines,
// block until the writer gives us the final count.
let count = reader_recv
.recv()
.expect("Failed to receive count from printer.");
println!("{}", count);
};
// Define the work the writer will do.
let writer_work = move || {
let mut line_count = 0;
loop {
match writer_recv.recv() {
Ok(msg) => {
println!("{}", msg);
line_count += 1;
}
Err(_) => break, // indicates the connection has been closed by the sender.
}
}
// Send the final count back to the reader.
writer_send
.send(line_count)
.expect("Failed to send line count from writer.");
drop(writer_send);
};
// Spawn each as a thread.
let reader_handle = thread::spawn(reader_work);
thread::spawn(writer_work);
reader_handle
.join()
.expect("Failed to join the reader thread.");
}