Решение на упр.13 задача 1 от Йосиф Хамед
Код
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
// =========================================================
// 1. JOB TRAIT (НЕ СЕ ПРОМЕНЯ)
// =========================================================
pub trait Job: Send + 'static {
type Output: Send + 'static;
type Error: Send + 'static;
fn run(self) -> Result<Self::Output, Self::Error>;
}
// =========================================================
// 2. ВЪТРЕШНИ СЪОБЩЕНИЯ (НЕ СЕ ПРОМЕНЯ)
// =========================================================
enum Message {
Run(Box<dyn FnOnce() + Send>),
Shutdown,
}
// =========================================================
// 3. THREAD POOL
// =========================================================
pub struct ThreadPool {
workers: Vec<thread::JoinHandle<()>>,
sender: mpsc::Sender<Message>,
}
impl ThreadPool {
pub fn new(worker_count: usize) -> Self {
let (sender, receiver) = mpsc::channel::<Message>();
let receiver = Arc::new(Mutex::new(receiver));
let mut workers = Vec::with_capacity(worker_count);
for _ in 0..worker_count {
let thread_receiver = Arc::clone(&receiver);
let handle = thread::spawn(move || loop {
let message = {
let rx = thread_receiver.lock().unwrap();
rx.recv().unwrap()
};
match message {
Message::Run(f) => f(),
Message::Shutdown => break,
}
});
workers.push(handle);
}
Self { workers, sender }
}
pub fn submit<J>(&self, job: J) -> mpsc::Receiver<Result<J::Output, J::Error>>
where
J: Job,
{
let (result_sender, result_receiver) = mpsc::channel();
let task = Box::new(move || {
let res = job.run();
let _ = result_sender.send(res);
});
self.sender.send(Message::Run(task)).unwrap();
result_receiver
}
}
// =========================================================
// 4. ГРАЦИОЗНО СПИРАНЕ
// =========================================================
impl Drop for ThreadPool {
fn drop(&mut self) {
for _ in &self.workers {
let _ = self.sender.send(Message::Shutdown);
}
for worker in self.workers.drain(..) {
let _ = worker.join();
}
}
}
