cs431_homework/hello_server/thread_pool.rs
1//! Thread pool that joins all thread when dropped.
2
3// NOTE: Crossbeam channels are MPMC, which means that you don't need to wrap the receiver in
4// Arc<Mutex<..>>. Just clone the receiver and give it to each worker thread.
5use std::sync::{Arc, Condvar, Mutex};
6use std::thread;
7
8use crossbeam_channel::{Sender, unbounded};
9
10struct Job(Box<dyn FnOnce() + Send + 'static>);
11
12#[derive(Debug)]
13struct Worker {
14 _id: usize,
15 thread: Option<thread::JoinHandle<()>>,
16}
17
18impl Drop for Worker {
19 /// When dropped, the thread's `JoinHandle` must be `join`ed. If the worker panics, then this
20 /// function should panic too.
21 ///
22 /// NOTE: The thread is detached if not `join`ed explicitly.
23 fn drop(&mut self) {
24 todo!()
25 }
26}
27
28/// Internal data structure for tracking the current job status. This is shared by worker closures
29/// via `Arc` so that the workers can report to the pool that it started/finished a job.
30#[derive(Debug, Default)]
31struct ThreadPoolInner {
32 job_count: Mutex<usize>,
33 empty_condvar: Condvar,
34}
35
36impl ThreadPoolInner {
37 /// Increment the job count.
38 fn start_job(&self) {
39 todo!()
40 }
41
42 /// Decrement the job count.
43 fn finish_job(&self) {
44 todo!()
45 }
46
47 /// Wait until the job count becomes 0.
48 ///
49 /// NOTE: We can optimize this function by adding another field to `ThreadPoolInner`, but let's
50 /// not care about that in this homework.
51 fn wait_empty(&self) {
52 todo!()
53 }
54}
55
56/// Thread pool.
57#[derive(Debug)]
58pub struct ThreadPool {
59 _workers: Vec<Worker>,
60 job_sender: Option<Sender<Job>>,
61 pool_inner: Arc<ThreadPoolInner>,
62}
63
64impl ThreadPool {
65 /// Create a new ThreadPool with `size` threads.
66 ///
67 /// # Panics
68 ///
69 /// Panics if `size` is 0.
70 pub fn new(size: usize) -> Self {
71 assert!(size > 0);
72
73 todo!()
74 }
75
76 /// Execute a new job in the thread pool.
77 pub fn execute<F>(&self, f: F)
78 where
79 F: FnOnce() + Send + 'static,
80 {
81 todo!()
82 }
83
84 /// Block the current thread until all jobs in the pool have been executed.
85 ///
86 /// NOTE: This method has nothing to do with `JoinHandle::join`.
87 pub fn join(&self) {
88 todo!()
89 }
90}
91
92impl Drop for ThreadPool {
93 /// When dropped, all worker threads' `JoinHandle` must be `join`ed. If the thread panicked,
94 /// then this function should panic too.
95 fn drop(&mut self) {
96 todo!()
97 }
98}