Hello.
In "The Rust Programming Language second edition", in the subchapter 20.3 "Graceful Shutdown and Cleanup", the listing 20-23 has a code which does not compile (which is normal):
struct Worker {
id: usize,
thread: thread::JoinHandle<()>,
}
pub struct ThreadPool {
workers: Vec<Worker>,
sender: mpsc::Sender<Job>,
}
impl Drop for ThreadPool {
fn drop(&mut self) {
for worker in &mut self.workers {
println!("Shutting down worker {}", worker.id);
worker.thread.join().unwrap(); // COMPILATION ERROR (which is normal)
}
}
}
The solution proposed by the book is to replace the struct Worker and the implementation of ThreadPool::drop with:
struct Worker {
id: usize,
thread: Option<thread::JoinHandle<()>>,
}
impl Drop for ThreadPool {
fn drop(&mut self) {
for worker in &mut self.workers {
println!("Shutting down worker {}", worker.id);
if let Some(thread) = worker.thread.take() {
thread.join().unwrap();
}
}
}
}
But I think that this workaround increases the memory consumption (due to the std::option::Option overhead) and decreases the compiler controls (because the "thread" member has a new possible value: None).
Is this workaround avoidable?
If no, I thought about a new feature: a customizable destructor.
This feature would allow to replace the normal destruction of the members of a struct with a call to a customizable function which takes ownership of the members.
Pseudocode example:
struct Worker {
id: usize,
thread: thread::JoinHandle<()>,
}
pub struct ThreadPool {
workers: Vec<Worker>,
sender: mpsc::Sender<Job>,
}
impl ThreadPool {
fn dtor(workers: Vec<Worker>, _sender: mpsc::Sender<Message>)
{
for worker in workers.into_iter() {
println!("Shutting down worker {}", worker.id);
worker.thread.join().unwrap();
}
}
}
In my pseudocode example, every destruction of a ThreadPool object would be replaced by a call to the destructor ThreadPool::dtor which takes ownership of the variable members of the ThreadPool object.
Another solution would be to let the destructor of Worker to call join:
impl Worker {
fn dtor(id: usize, thread: thread::JoinHandle<()>)
{
println!("Shutting down worker {}", id);
thread.join().unwrap();
}
}
But I don't know Rust well yet (I just finished reading the book), so I am not ready to write a Rust RFC yet.