72 lines
2.1 KiB
Plaintext
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.");
|
|
}
|