|
|
|
|
|
|
|
|
use std::thread; |
|
|
use std::thread; |
|
|
use std::sync::{mpsc, Mutex, Arc}; |
|
|
use std::sync::{mpsc, Mutex, Arc}; |
|
|
|
|
|
|
|
|
|
|
|
enum Message { |
|
|
|
|
|
NewJob(Job), |
|
|
|
|
|
Terminate |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
pub struct ThreadPool{ |
|
|
pub struct ThreadPool{ |
|
|
workers: Vec<Worker>, |
|
|
workers: Vec<Worker>, |
|
|
sender: mpsc::Sender<Job>, |
|
|
|
|
|
|
|
|
sender: mpsc::Sender<Message>, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
type Job = Box<dyn FnOnce() + Send + 'static>; |
|
|
type Job = Box<dyn FnOnce() + Send + 'static>; |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
pub fn execute<F>(&self, f: F) |
|
|
pub fn execute<F>(&self, f: F) |
|
|
where F: FnOnce() + Send + 'static |
|
|
|
|
|
|
|
|
where |
|
|
|
|
|
F: FnOnce() + Send + 'static |
|
|
{ |
|
|
{ |
|
|
let job = Box::new(f); |
|
|
let job = Box::new(f); |
|
|
self.sender.send(job).unwrap(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.sender.send(Message::NewJob(job)).unwrap(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// pub fn spawn<F, T>(f: F) -> JoinHandle<T> |
|
|
// pub fn spawn<F, T>(f: F) -> JoinHandle<T> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Drop for ThreadPool { |
|
|
impl Drop for ThreadPool { |
|
|
fn drop(&mut self) { |
|
|
fn drop(&mut self) { |
|
|
|
|
|
println!("Sending terminate message to all workers."); |
|
|
|
|
|
for _ in &mut self.workers { |
|
|
|
|
|
self.sender.send(Message::Terminate).unwrap(); |
|
|
|
|
|
} |
|
|
|
|
|
println!("Shutting down all workers."); |
|
|
|
|
|
|
|
|
for worker in &mut self.workers { |
|
|
for worker in &mut self.workers { |
|
|
println!("Shutting down worker {}", worker.id); |
|
|
|
|
|
|
|
|
println!("Shutting down worker {}.", worker.id); |
|
|
|
|
|
|
|
|
worker.thread.join().unwrap(); |
|
|
|
|
|
|
|
|
if let Some(thread) = worker.thread.take() { |
|
|
|
|
|
thread.join().unwrap(); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
struct Worker { |
|
|
struct Worker { |
|
|
id: usize, |
|
|
id: usize, |
|
|
thread: thread::JoinHandle<()>, |
|
|
|
|
|
|
|
|
thread: Option<thread::JoinHandle<()>>, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
impl Worker { |
|
|
impl Worker { |
|
|
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker { |
|
|
|
|
|
let thread = thread::spawn(move || { |
|
|
|
|
|
|
|
|
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> |
|
|
|
|
|
Worker { |
|
|
|
|
|
|
|
|
|
|
|
let thread = thread::spawn(move ||{ |
|
|
loop { |
|
|
loop { |
|
|
let job = receiver.lock().unwrap().recv().unwrap(); |
|
|
|
|
|
|
|
|
let message = receiver.lock().unwrap().recv().unwrap(); |
|
|
|
|
|
|
|
|
|
|
|
match message { |
|
|
|
|
|
Message::NewJob(job) => { |
|
|
|
|
|
println!("Worker {} got a job; executing.", id); |
|
|
|
|
|
|
|
|
println!("Worker {} got a job, executing.", id); |
|
|
|
|
|
|
|
|
job(); |
|
|
|
|
|
}, |
|
|
|
|
|
Message::Terminate => { |
|
|
|
|
|
println!("Worker {} was told to terminate.", id); |
|
|
|
|
|
|
|
|
job(); |
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
}, |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
Worker { |
|
|
Worker { |
|
|
id, |
|
|
id, |
|
|
thread, |
|
|
|
|
|
|
|
|
thread: Some(thread), |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |