I want to count the frequency of words within a large string.
The simple single threaded solution looks like this
use hashbrown::HashMap;
fn main() {
let buffer = String::from("Hello World Hello Rust");
let mut frequency: HashMap<&str, u32> = HashMap::new();
for word in buffer.split_whitespace() {
*frequency.entry(word).or_insert(0) += 1;
}
}
Then I tried to add some multi threading capabilities and ended up with the code below:
extern crate crossbeam;
use hashbrown::HashMap;
use std::sync::{Arc, Mutex};
fn main() {
let buffer = Arc::new(String::from("Hello World Hello Rust"));
let frequency: Arc<Mutex<HashMap<&str, u32>>> = Arc::new(Mutex::new(HashMap::new()));
crossbeam::scope(|scope| {
for _ in 0..1 {
let buffer = buffer.clone();
let frequency = frequency.clone();
scope.spawn(move |_| {
for word in buffer.split_whitespace() {
let mut frequency = frequency.lock().unwrap();
*frequency.entry(word).or_insert(0) += 1;
}
});
}
});
}
The compiler fails with the following message:
error[E0597]: `buffer` does not live long enough
--> src/main.rs:16:29
|
13 | let frequency = frequency.clone();
| --------- lifetime `'1` appears in the type of `frequency`
...
16 | for word in buffer.split_whitespace() {
| ^^^^^^ borrowed value does not live long enough
17 | let mut frequency = frequency.lock().unwrap();
18 | *frequency.entry(word).or_insert(0) += 1;
| --------------------- argument requires that `buffer` is borrowed for `'1`
19 | }
20 | });
| - `buffer` dropped here while still borrowed
To simplify the code I removed string chunking and only spawn 1 thread within the for loop.