From 8000d1db294811645e4efdcb9d4adc4f73029f67 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 4 Oct 2023 01:57:18 -0700 Subject: [PATCH] gpt: park thread --- src/worker.rs | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/worker.rs b/src/worker.rs index e7dcb5b..2898d04 100644 --- a/src/worker.rs +++ b/src/worker.rs @@ -1,15 +1,16 @@ use std::thread; use std::sync::{mpsc,Arc}; use parking_lot::{Mutex,Condvar}; +use std::sync::atomic::{AtomicBool, Ordering}; struct Worker { id: usize, receiver: Arc<(Mutex>, Condvar)>, - is_active: Arc>, + is_active: Arc, } impl Worker { - fn new(id: usize, receiver: Arc<(Mutex>, Condvar)>, is_active: Arc>) -> Worker { + fn new(id: usize, receiver: Arc<(Mutex>, Condvar)>, is_active: Arc) -> Worker { Worker { id, receiver, is_active } } @@ -31,8 +32,8 @@ impl Worker { } // Set is_active to false when the worker is done - *self.is_active.lock() = false; - self.receiver.1.notify_all(); + self.is_active.store(false, Ordering::SeqCst); + self.receiver.1.notify_one(); }); } } @@ -42,38 +43,41 @@ type Task = String; fn main() { let (sender, receiver) = mpsc::channel::(); let receiver = Arc::new((Mutex::new(receiver), Condvar::new())); - let is_active = Arc::new(Mutex::new(true)); + let is_active = Arc::new(AtomicBool::new(true)); - // Create the first worker thread + // Create the worker thread let worker = Worker::new(1, Arc::clone(&receiver), Arc::clone(&is_active)); - // Start the first worker thread + // Start the worker thread worker.start(); - // Send tasks to the first worker + // Send tasks to the worker for i in 0..5 { let task = format!("Task {}", i); sender.send(task).unwrap(); } - // Optional: Signal the first worker to stop (in a real-world scenario) + // Optional: Signal the worker to stop (in a real-world scenario) // sender.send("STOP".to_string()).unwrap(); - // Sleep to allow the first worker thread to finish processing + // Sleep to allow the worker thread to finish processing thread::sleep(std::time::Duration::from_secs(2)); - // Check if the first worker is still active - let is_first_worker_active = *is_active.lock(); + // Check if the worker is still active + let is_worker_active = is_active.load(Ordering::SeqCst); - if !is_first_worker_active { - // If the first worker is done, spawn a new worker - let new_worker = Worker::new(2, Arc::clone(&receiver), Arc::clone(&is_active)); - new_worker.start(); + if !is_worker_active { + // If the worker is done, signal it to process a new task + is_active.store(true, Ordering::SeqCst); + let (ref lock, ref cvar) = &*receiver; + cvar.notify_one(); + + // Send a new task sender.send("New Task".to_string()).unwrap(); - // Wait for the new worker to finish processing - let _ = receiver.1.wait_while(is_active.lock(), |&active| active); + // Wait for the worker to finish processing + cvar.wait_while(lock.lock(), |&active| active); } else { - println!("First worker is still active. Skipping new worker."); + println!("Worker is still active. Skipping new task."); } }