X-Git-Url: https://git.ralfj.de/rust-101.git/blobdiff_plain/5f6e02d64e3789115ea4327a045b8ad3c39b1808..98dafe0138b8bf6584b8d9e86a74a580bb034a26:/workspace/src/part12.rs?ds=inline
diff --git a/workspace/src/part12.rs b/workspace/src/part12.rs
index 1d75bfd..4996ac1 100644
--- a/workspace/src/part12.rs
+++ b/workspace/src/part12.rs
@@ -1,5 +1,5 @@
-// Rust-101, Part 12: Concurrency (WIP)
-// =================
+// Rust-101, Part 12: Concurrency, Arc, Send
+// =========================================
use std::io::prelude::*;
use std::{io, fs, thread};
@@ -9,23 +9,22 @@ use std::sync::Arc;
// Before we come to the actual code, we define a data-structure `Options` to store all the information we need
// to complete the job: Which files to work on, which pattern to look for, and how to output.
-// Besides just printing all the matching lines, we will also offer to count them, or alternatively to sort them.
#[derive(Clone,Copy)]
-enum OutputMode {
+pub enum OutputMode {
Print,
SortAndPrint,
Count,
}
use self::OutputMode::*;
-struct Options {
- files: Vec,
- pattern: String,
- output_mode: OutputMode,
+pub struct Options {
+ pub files: Vec,
+ pub pattern: String,
+ pub output_mode: OutputMode,
}
-// The first functions reads the files, and sends every line over the `out_channel`.
+// The first function reads the files, and sends every line over the `out_channel`.
fn read_files(options: Arc, out_channel: SyncSender) {
for file in options.files.iter() {
// First, we open the file, ignoring any errors.
@@ -43,11 +42,13 @@ fn read_files(options: Arc, out_channel: SyncSender) {
// The second function filters the lines it receives through `in_channel` with the pattern, and sends
// matches via `out_channel`.
-fn filter_lines(options: Arc, in_channel: Receiver, out_channel: SyncSender) {
+fn filter_lines(options: Arc,
+ in_channel: Receiver,
+ out_channel: SyncSender) {
// We can simply iterate over the channel, which will stop when the channel is closed.
for line in in_channel.iter() {
// `contains` works on lots of types of patterns, but in particular, we can use it to test whether
- // one string is contained in another.
+ // one string is contained in another. This is another example of Rust using traits as substitute for overloading.
if line.contains(&options.pattern) {
unimplemented!()
}
@@ -70,7 +71,7 @@ fn output_lines(options: Arc, in_channel: Receiver) {
},
SortAndPrint => {
// We are asked to sort the matching lines before printing. So let's collect them all in a local vector...
- let data: Vec = in_channel.iter().collect();
+ let mut data: Vec = in_channel.iter().collect();
// ...and implement the actual sorting later.
unimplemented!()
}
@@ -79,11 +80,11 @@ fn output_lines(options: Arc, in_channel: Receiver) {
// With the operations of the three threads defined, we can now implement a function that performs grepping according
// to some given options.
-fn run(options: Options) {
+pub fn run(options: Options) {
// We move the `options` into an `Arc`, as that's what the thread workers expect.
let options = Arc::new(options);
- // Set up the channels. Use `sync_channel` with buffer-size of 16 to avoid needlessly filling RAM.
+ // This sets up the channels. We use a `sync_channel` with buffer-size of 16 to avoid needlessly filling RAM.
let (line_sender, line_receiver) = sync_channel(16);
let (filtered_sender, filtered_receiver) = sync_channel(16);
@@ -93,7 +94,9 @@ fn run(options: Options) {
// Same with the filter thread.
let options2 = options.clone();
- let handle2 = thread::spawn(move || filter_lines(options2, line_receiver, filtered_sender));
+ let handle2 = thread::spawn(move || {
+ filter_lines(options2, line_receiver, filtered_sender)
+ });
// And the output thread.
let options3 = options.clone();
@@ -105,17 +108,19 @@ fn run(options: Options) {
handle3.join().unwrap();
}
-// Now we have all the pieces together for testing our `rgrep` with some hard-coded options.
+// Now we have all the pieces together for testing our rgrep with some hard-coded options.
pub fn main() {
let options = Options {
- files: vec!["src/part10.rs".to_string(), "src/part11.rs".to_string(), "src/part12.rs".to_string()],
+ files: vec!["src/part10.rs".to_string(),
+ "src/part11.rs".to_string(),
+ "src/part12.rs".to_string()],
pattern: "let".to_string(),
output_mode: Print
};
run(options);
}
-// **Exercise 12.1**: Change `rgrep` such that it prints now only the matching lines, but also the name of the file
+// **Exercise 12.1**: Change rgrep such that it prints not only the matching lines, but also the name of the file
// and the number of the line in the file. You will have to change the type of the channels from `String` to something
// that records this extra information.