Hi!
I just started learning Rust and coming from the scripting/runtime world I am still getting used to the new concepts Rust provides.
My question is quite specific, though, about threads, mutexes and locking:
To get more acquainted to the language, I am trying to write a small proof-of-concept parallel ftp uploader, utilizing a thread pool and a connection pool.
I have managed to appease the compiler to a point where I can run the program and get connections to the server. I am just not sure the way I am locking the resources really results in work being done in parallel or whether I have just created an overly-complicated sequential procedure using threads instead.
I hope someone could tell me if I'm using the mutex locks correctly and give me feedback on what I could improve here:
extern crate threadpool;
extern crate ftp;
use threadpool::ThreadPool;
use ftp::FTPStream;
use std::sync::{Mutex, mpsc};
use std::sync::Arc;
fn main() {
let connections = 4;
let jobs = 8;
let thread_pool = ThreadPool::new(connections);
let (tx, rx) = mpsc::channel();
// prepare connection pool
let mut conn_pool = Vec::with_capacity(connections);
for _ in 0..connections {
let mut stream = FTPStream::connect("127.0.0.1".to_string(), 21).unwrap();
stream.login("anonymous", "anonymous").unwrap();
conn_pool.push(Mutex::new(stream));
}
let protected_conn_pool = Arc::new(Mutex::new(conn_pool));
for i in 0..jobs {
println!("starting thread {}", i);
let tx = tx.clone();
let protected_conn_pool = protected_conn_pool.clone(); // Arc++
thread_pool.execute(move|| {
let conn_pool = protected_conn_pool.lock().unwrap();
let mut stream = None;
// find a connection that is not in use
conn_pool.iter().find(|&conn| {
match conn.try_lock() {
Ok(s) => { stream = Some(s); true },
Err(_) => false
}
});
// do something productive with the connection...
match stream {
Some(mut s) => {
println!("DIR: {}", s.current_dir().unwrap());
},
None => { }
}
println!("finished thread {}", i);
tx.send(()).unwrap();
});
}
// wait for the all jobs to finish
rx.iter().take(jobs).collect::<Vec<_>>();
}