This is an elegant, very small, Rust library for simple multi-threading. The use case below is 2 .. 1,000,000 of the Collatz Conjecture, but obviously it's suitable for many simple tasks. I called it Stables and Horses because the idea is that Horses are functions that are then sent from the stables as threads. The code is provided as-is with no support. I am not a programmer. I like computing but I also hate it. I have used this successfully with GiBs sized files, but use buffered IO, at least on file-system writes, because unbuffered IO can be obnoxiously slow and unpredictable.
/// Very simple, quite efficient threading model for general tasks
///
use std::sync::{Arc, Mutex};
use std::thread;
// Type alias for an Option on a function
type Horse = Option<Box<dyn Fn() + 'static + Send>>;
pub struct Stables {
count: usize,
horses: Arc<Mutex<Vec<Horse>>>,
}
impl Stables {
pub fn new(size: usize) -> Stables {
let mut temp_horses: Vec<Horse> = Vec::with_capacity(size);
for _ in 0..size {
temp_horses.push(None);
}
Stables {
count: size,
horses: Arc::new(Mutex::new(temp_horses)),
}
}
pub fn new_race(&self, func: Box<dyn Fn() + 'static + Send>) {
let my_horses = Arc::clone(&self.horses);
let mut my_horses = my_horses.lock().unwrap();
for x in my_horses.iter_mut() {
match x {
Some(_) => continue,
None => {
*x = Some(func);
return ();
},
}
}
}
pub fn off(&self) {
let my_horses = Arc::clone(&self.horses);
let mut my_horses = my_horses.lock().unwrap();
let mut threads = Vec::with_capacity(self.count);
for x in my_horses.iter_mut() {
match x {
Some(_) => {
let q = x.take();
match q {
Some(f) => {
let clipclop = thread::spawn(move || {
f()
});
threads.push(clipclop);
}
None => {
continue;
}
}
}
None => {
continue;
}
}
}
for x in threads {
x.join().unwrap();
}
}
}
use stables::Stables;
use std::sync::{Mutex,Arc};
fn main() {
let test_out = Arc::new(Mutex::new(String::new()));
let highest = Arc::new(Mutex::new(0));
let ref_one = Arc::clone(&test_out);
let ref_two = Arc::clone(&test_out);
let count1 = Arc::clone(&highest);
let count2 = Arc::clone(&highest);
let my_stables = Stables::new(4);
let job_one = move || {
for x in 2..5_000_00 {
let c = collatz(x);
let h = *count1.lock().unwrap();
if c>h {
println!("{:?}: {:?}", x, c);
*count1.lock().unwrap()=c;
}
}
*ref_one.lock().unwrap()=String::from("Hello");
};
let job_two = move || {
for x in 5_000_00..=1_000_000 {
let c = collatz(x);
let h = *count2.lock().unwrap();
if c>h {
println!("{:?}: {:?}", x, c);
*count2.lock().unwrap()=c;
}
}
*ref_two.lock().unwrap()=String::from("Goodbye");
};
my_stables.new_race(Box::new(job_one));
my_stables.new_race(Box::new(job_two));
my_stables.off();
my_stables.off();
println!("{:?}", test_out);
}
fn collatz(number: u64) -> usize{
let mut number = number;
let mut list: Vec<u64> = Vec::new();
while number!=1 {
list.push(number);
if number%2 == 0 {
number=number/2;
} else {
number = (3*number) + 1;
}
}
list.push(number);
return list.len()-1;
}
back
© John B Everitt