Compare commits
	
		
			No commits in common. "da89562800ccb48bb1823784fcf0c6405ee08561" and "ebf0a894063fa68097a297d99e683237f33dcdef" have entirely different histories.
		
	
	
		
			da89562800
			...
			ebf0a89406
		
	
		
| @ -10,28 +10,26 @@ use std::thread; | ||||
| use std::time::Duration; | ||||
| 
 | ||||
| fn main() { | ||||
|     let addr = "127.0.0.1:7878"; | ||||
|     let listener = TcpListener::bind(&addr).unwrap(); | ||||
|     println!("Listening on http://{}", &addr); | ||||
| 
 | ||||
|     let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); | ||||
|     let counter = Arc::new(Mutex::new(0usize)); | ||||
| 
 | ||||
|     let tasks = ThreadPool::new(100); | ||||
| 
 | ||||
|     for stream in listener.incoming()/*.take(2)*/ { | ||||
|         println!("accepted new connection"); | ||||
| 
 | ||||
|         if let Ok(stream) = stream { | ||||
|     for stream in listener.incoming() { | ||||
|         let stream = stream.unwrap(); | ||||
|         let counter = Arc::clone(&counter); | ||||
| 
 | ||||
|         tasks.run(move || { | ||||
|             { | ||||
|                 // in a subscope to release borrow automatically
 | ||||
|                 let mut count = counter.lock().unwrap(); | ||||
|                 *count += 1; | ||||
|             } | ||||
|             handle_connection(counter, stream); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|     println!("Shutting down..."); | ||||
| } | ||||
| 
 | ||||
| fn handle_connection(counter: Arc<Mutex<usize>>, mut stream: TcpStream) { | ||||
|     let mut buffer = [0; 512]; | ||||
| 
 | ||||
| @ -39,8 +37,7 @@ fn handle_connection(counter: Arc<Mutex<usize>>, mut stream: TcpStream) { | ||||
| 
 | ||||
|     { | ||||
|         // in a subscope to unlock automatically
 | ||||
|         let mut count = counter.lock().unwrap(); | ||||
|         *count += 1; | ||||
|         let count = counter.lock().unwrap(); | ||||
|         println!("Request: {}\n{}", count, String::from_utf8_lossy(&buffer[..])); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										54
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -16,65 +16,29 @@ type Job = Box<dyn FnBox + Send + 'static>; | ||||
| 
 | ||||
| struct Worker { | ||||
|     id: usize, | ||||
|     thread: Option<thread::JoinHandle<()>>, | ||||
| } | ||||
| 
 | ||||
| enum Message { | ||||
|   NewJob(Job), | ||||
|   Terminate, | ||||
|     thread: thread::JoinHandle<()>, | ||||
| } | ||||
| 
 | ||||
| impl Worker { | ||||
|     pub fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker { | ||||
|     pub fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker { | ||||
|         Worker { | ||||
|             id, | ||||
|             thread: Some(thread::spawn(move || { | ||||
|             thread: thread::spawn(move || { | ||||
|                 loop { | ||||
|                     if let Ok(job) = receiver.lock().expect("unrecoverable poisened panicked thread state").recv() { | ||||
|                         match job { | ||||
|                             Message::NewJob(job) => { | ||||
|                     let job = receiver.lock().expect("unrecoverable poisened panicked thread state").recv().unwrap(); | ||||
| 
 | ||||
|                     println!("such busy, so worker #{}!", id); | ||||
| 
 | ||||
|                     job.call_box(); | ||||
|                 } | ||||
|                             Message::Terminate => { | ||||
|                                 println!("such sad, so dead #{}!", id); | ||||
|                                 break; | ||||
|                             } | ||||
|                         } | ||||
|                     } else { | ||||
|                         // TODO respawn? (unless in terminate mode)
 | ||||
|                         // or why would the recv fail? already terminated?
 | ||||
|                         // thread panic not handled?
 | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             })), | ||||
|             }), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct ThreadPool { | ||||
|     workers: Vec<Worker>, | ||||
|     sender: mpsc::Sender<Message>, | ||||
| } | ||||
| 
 | ||||
| impl Drop for ThreadPool { | ||||
|     fn drop(&mut self) { | ||||
|         // Each worker will only receive Terminate once
 | ||||
|         for _ in &mut self.workers { | ||||
|             self.sender.send(Message::Terminate).unwrap(); | ||||
|         } | ||||
| 
 | ||||
|         // Each worker will join once complete
 | ||||
|         for worker in &mut self.workers { | ||||
|             println!("Shutting down worker {} ...", worker.id); | ||||
| 
 | ||||
|             if let Some(thread) = worker.thread.take() { | ||||
|                 thread.join().unwrap(); | ||||
|                 println!("Killed {}!", worker.id); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     sender: mpsc::Sender<Job>, | ||||
| } | ||||
| 
 | ||||
| impl ThreadPool { | ||||
| @ -100,6 +64,6 @@ impl ThreadPool { | ||||
|     pub fn run<F: FnOnce() + Send + 'static>(&self, task: F) | ||||
|     { | ||||
|         let task = Box::new(task); | ||||
|         self.sender.send(Message::NewJob(task)).unwrap(); | ||||
|         self.sender.send(task).unwrap(); | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user