Created
February 5, 2015 20:14
-
-
Save stefanoc/c85857b124b31c3ca86b to your computer and use it in GitHub Desktop.
Rust word counter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "wc" | |
version = "0.0.1" | |
authors = ["stefano"] | |
[dependencies] | |
regex = "0.1.12" | |
regex_macros = "0.1.6" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(core)] | |
#![feature(collections)] | |
#![feature(std_misc)] | |
#![feature(io)] | |
#![feature(plugin)] | |
#[plugin] #[no_link] extern crate regex_macros; | |
extern crate regex; | |
use std::collections::btree_map::{BTreeMap, Occupied, Vacant}; | |
use std::old_io as io; | |
use std::sync::mpsc::channel; | |
use std::sync::mpsc::{Sender}; | |
use std::thread::Thread; | |
macro_rules! val [ | |
($inp:expr) => { match $inp { Ok(val) => val, _ => { panic!("Value expected"); } } } | |
]; | |
macro_rules! stop [ | |
($tx:ident) => { $tx.send(STOP.to_string()).ok(); } | |
]; | |
macro_rules! send [ | |
($tx:expr, $val:expr) => { $tx.send($val).ok(); } | |
]; | |
macro_rules! map_incr [ | |
($dict:expr, $key:expr) => { | |
match $dict.entry($key) { | |
Vacant(entry) => { entry.insert(1); }, | |
Occupied(mut entry) => *entry.get_mut() += 1, | |
} | |
} | |
]; | |
static STOP: &'static str = ".STOP"; | |
fn spawn_line_worker(tx_word: Sender<String>) -> Sender<String> { | |
let (tx_line, rx_line) = channel::<String>(); | |
Thread::spawn(move || { | |
let re = regex!(r"\w+"); | |
loop { | |
let line = rx_line.recv().unwrap(); | |
if &line[] == STOP { | |
stop!(tx_word); | |
break; | |
} | |
for (a, b) in re.find_iter(&line[]) { | |
send!(tx_word, line.slice_chars(a, b).to_string()); | |
} | |
} | |
}); | |
return tx_line; | |
} | |
fn main() { | |
let pool_size = 4; | |
let mut line_workers = vec![]; | |
let (tx_word, rx_word) = channel::<String>(); | |
for _ in range(0, pool_size) { line_workers.push(spawn_line_worker(tx_word.clone())); } | |
let counter = Thread::scoped(move || -> BTreeMap<_, _> { | |
let mut dict = BTreeMap::new(); | |
let mut finished = 0; | |
loop { | |
let word = rx_word.recv().unwrap(); | |
if &word[] == STOP { | |
finished += 1; | |
if finished == pool_size { break; } | |
} else { | |
map_incr!(dict, word); | |
} | |
} | |
return dict; | |
}); | |
let mut line_no = 0; | |
for line in io::stdin().lock().lines() { | |
send!(line_workers[line_no % pool_size], line.unwrap()); | |
line_no += 1; | |
} | |
for tx in line_workers.iter() { stop!(tx); } | |
let dict = val!(counter.join()); | |
println!("{:?}", dict); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment