@@ -3,7 +3,8 @@ use std::{sync::{mpsc, Arc, Mutex}, thread};
3
3
4
4
pub struct ThreadPool {
5
5
workers : Vec < Worker > ,
6
- sender : mpsc:: Sender < Job > ,
6
+ // Option<> to wrap sender so that ownership can be taken out sometime later.
7
+ sender : Option < mpsc:: Sender < Job > > ,
7
8
}
8
9
9
10
impl ThreadPool {
@@ -17,34 +18,57 @@ impl ThreadPool{
17
18
workers. push ( Worker :: new ( id, Arc :: clone ( & receiver) ) ) ;
18
19
19
20
}
20
- ThreadPool { workers, sender}
21
+ ThreadPool { workers, sender : Some ( sender ) }
21
22
}
22
23
23
24
pub fn execute < F > ( & self , f : F )
24
25
where
25
26
F : FnOnce ( ) + Send + ' static ,
26
27
{
27
28
let job = Box :: new ( f) ;
28
- self . sender . send ( job) . unwrap ( ) ;
29
29
30
+ self . sender . as_ref ( ) . expect ( "Fail to unwrap self.sender" ) . send ( job) . unwrap ( ) ;
30
31
}
31
32
}
32
33
34
+ impl Drop for ThreadPool {
35
+ fn drop ( & mut self ) {
36
+ //drop() can handle Option<T>?
37
+ drop ( self . sender . take ( ) ) ;
38
+ for worker in & mut self . workers {
39
+ eprintln ! ( "Shutting down work {}" , worker. id) ;
40
+ if let Some ( thread) = worker. thread . take ( ) {
41
+ thread. join ( ) . unwrap ( ) ;
42
+ }
43
+ }
44
+ }
45
+ }
46
+
33
47
type Job = Box < dyn FnOnce ( ) + Send + ' static > ;
34
48
35
49
struct Worker {
36
50
id : usize ,
37
- thread : thread:: JoinHandle < ( ) > ,
51
+ // Option<> to wrap thread so that ownership can be taken out sometime later.
52
+ thread : Option < thread:: JoinHandle < ( ) > > ,
38
53
}
39
54
40
55
impl Worker {
41
56
fn new ( id : usize , receiver : Arc < Mutex < mpsc:: Receiver < Job > > > ) -> Worker {
42
57
eprintln ! ( "Worker {id} constructed and spawned a thread that loops forever over a receiver." ) ;
43
58
let thread = thread:: spawn ( move || loop {
44
- let job = receiver. lock ( ) . unwrap ( ) . recv ( ) . unwrap ( ) ;
45
- eprintln ! ( "Worker {id} got a job and is to execute it." ) ;
46
- job ( ) ;
59
+ let mesg = receiver. lock ( ) . unwrap ( ) . recv ( ) ;
60
+ match mesg {
61
+ Ok ( job) => {
62
+ eprintln ! ( "Worker {id} got a job and is to execute it." ) ;
63
+ job ( ) ;
64
+ }
65
+ Err ( err) => {
66
+ eprintln ! ( "Worker {id} received an error {:?} and is shutting down." , err) ;
67
+ break ;
68
+ }
69
+ }
47
70
} ) ;
48
- Worker { id, thread}
71
+ // specify the field name for thread as it is Some(thread), not simply thread.
72
+ Worker { id, thread : Some ( thread) }
49
73
}
50
74
}
0 commit comments