]> piware.de Git - learn-rust.git/commitdiff
simple-http: Implement ThreadPool messaging
authorMartin Pitt <martin@piware.de>
Sun, 19 Sep 2021 09:37:29 +0000 (11:37 +0200)
committerMartin Pitt <martin@piware.de>
Sun, 19 Sep 2021 09:37:29 +0000 (11:37 +0200)
simple-http/src/lib.rs

index ff8bc4f3f8f63faecf47626d0f3a1ecff1082902..4b7d7362afa241b94f34a2e3166f6c44288eb90a 100644 (file)
@@ -1,18 +1,27 @@
 use std::thread;
+use std::sync::{Arc, mpsc, Mutex};
+
+type Job = Box<dyn FnOnce() + Send + 'static>;
 
 struct Worker {
     id: usize,
-    thread: thread::JoinHandle<()>,
+    thread: Option<thread::JoinHandle<()>>,
 }
 
 impl Worker {
-    fn new(id: usize) -> Worker {
-        Worker { id, thread: thread::spawn(|| {}) }
+    fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+        let thread = Some(thread::spawn(move || loop {
+            let job = receiver.lock().unwrap().recv().unwrap();
+            println!("Worker {} got a job, executing", id);
+            job();
+        }));
+        Worker { id, thread }
     }
 }
 
 pub struct ThreadPool {
     workers: Vec<Worker>,
+    sender: mpsc::Sender<Job>,
 }
 
 impl ThreadPool {
@@ -25,16 +34,31 @@ impl ThreadPool {
         assert!(size > 0);
         let mut workers = Vec::with_capacity(size);
 
+        let (sender, receiver) = mpsc::channel();
+        let receiver = Arc::new(Mutex::new(receiver));
+
         for id in 0..size {
-            workers.push(Worker::new(id));
+            workers.push(Worker::new(id, Arc::clone(&receiver)));
         }
 
-        ThreadPool { workers }
+        ThreadPool { workers, sender }
     }
 
     pub fn execute<F>(&self, f: F)
     where F: FnOnce() + Send + 'static
     {
-        thread::spawn(f);
+        self.sender.send(Box::new(f)).unwrap();
+    }
+}
+
+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();
+            }
+        }
     }
 }