// rust/01-basic-threading.rs/*Basic threading patterns and best practices for Rust*/usestd::thread;usestd::sync::{Arc,Mutex,RwLock};usestd::sync::mpsc;usestd::time::Duration;/// A thread-safe counter using Arc and Mutex.pubstructThreadSafeCounter{count:Arc<Mutex<u32>>,}implThreadSafeCounter{pubfnnew()->Self{Self{count:Arc::new(Mutex::new(0)),}}pubfnincrement(&self){letmutcount=self.count.lock().unwrap();*count+=1;}pubfnget_count(&self)->u32{letcount=self.count.lock().unwrap();*count}pubfnincrement_by(&self,amount:u32){letmutcount=self.count.lock().unwrap();*count+=amount;}}implCloneforThreadSafeCounter{fnclone(&self)->Self{Self{count:Arc::clone(&self.count),}}}/// A thread-safe data structure using RwLock for read-write access.pubstructThreadSafeData<T>{data:Arc<RwLock<T>>,}impl<T>ThreadSafeData<T>{pubfnnew(data:T)->Self{Self{data:Arc::new(RwLock::new(data)),}}pubfnread<F,R>(&self,f:F)->RwhereF:FnOnce(&T)->R,{letdata=self.data.read().unwrap();f(&data)}pubfnwrite<F,R>(&self,f:F)->RwhereF:FnOnce(&mutT)->R,{letmutdata=self.data.write().unwrap();f(&mutdata)}}impl<T>CloneforThreadSafeData<T>{fnclone(&self)->Self{Self{data:Arc::clone(&self.data),}}}/// Demonstrates thread communication using channels.pubstructThreadCommunicator{sender:mpsc::Sender<String>,receiver:mpsc::Receiver<String>,}implThreadCommunicator{pubfnnew()->Self{let(sender,receiver)=mpsc::channel();Self{sender,receiver}}pubfnsend(&self,message:String)->Result<(),mpsc::SendError<String>>{self.sender.send(message)}pubfnreceive(&self)->Result<String,mpsc::RecvError>{self.receiver.recv()}pubfntry_receive(&self)->Result<String,mpsc::TryRecvError>{self.receiver.try_recv()}}/// Demonstrates thread pool pattern.pubstructThreadPool{workers:Vec<thread::JoinHandle<()>>,sender:mpsc::Sender<Job>,}typeJob=Box<dynFnOnce()+Send+'static>;implThreadPool{pubfnnew(size:usize)->Self{let(sender,receiver)=mpsc::channel();letreceiver=Arc::new(Mutex::new(receiver));letmutworkers=Vec::with_capacity(size);foridin0..size{letreceiver=Arc::clone(&receiver);letworker=thread::spawn(move||{loop{letjob=receiver.lock().unwrap().recv();matchjob{Ok(job)=>{println!("Worker {} got a job; executing.",id);job();}Err(_)=>{println!("Worker {} disconnected; shutting down.",id);break;}}}});workers.push(worker);}Self{workers,sender}}pubfnexecute<F>(&self,f:F)whereF:FnOnce()+Send+'static,{letjob=Box::new(f);self.sender.send(job).unwrap();}}implDropforThreadPool{fndrop(&mutself){drop(&self.sender);forworkerinself.workers.drain(..){worker.join().unwrap();}}}/// Demonstrates thread-safe queue pattern.pubstructThreadSafeQueue<T>{queue:Arc<Mutex<Vec<T>>>,not_empty:Arc<Mutex<()>>,}impl<T>ThreadSafeQueue<T>{pubfnnew()->Self{Self{queue:Arc::new(Mutex::new(Vec::new())),not_empty:Arc::new(Mutex::new(())),}}pubfnpush(&self,item:T){letmutqueue=self.queue.lock().unwrap();queue.push(item);}pubfnpop(&self)->Option<T>{letmutqueue=self.queue.lock().unwrap();queue.pop()}pubfnlen(&self)->usize{letqueue=self.queue.lock().unwrap();queue.len()}pubfnis_empty(&self)->bool{letqueue=self.queue.lock().unwrap();queue.is_empty()}}impl<T>CloneforThreadSafeQueue<T>{fnclone(&self)->Self{Self{queue:Arc::clone(&self.queue),not_empty:Arc::clone(&self.not_empty),}}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_thread_safe_counter(){letcounter=ThreadSafeCounter::new();counter.increment();counter.increment_by(5);assert_eq!(counter.get_count(),6);}#[test]fntest_thread_safe_data(){letdata=ThreadSafeData::new(42);letresult=data.read(|x|*x);assert_eq!(result,42);data.write(|x|*x=100);letresult=data.read(|x|*x);assert_eq!(result,100);}#[test]fntest_thread_communicator(){letcommunicator=ThreadCommunicator::new();communicator.send("Hello".to_string()).unwrap();letmessage=communicator.receive().unwrap();assert_eq!(message,"Hello");}#[test]fntest_thread_safe_queue(){letqueue=ThreadSafeQueue::new();queue.push(1);queue.push(2);queue.push(3);assert_eq!(queue.len(),3);assert_eq!(queue.pop(),Some(3));assert_eq!(queue.pop(),Some(2));assert_eq!(queue.pop(),Some(1));assert!(queue.is_empty());}}
// rust/03-parallel-processing.rs/*Parallel processing patterns and best practices for Rust*/userayon::prelude::*;usestd::sync::Arc;usestd::collections::HashMap;/// Demonstrates parallel processing with Rayon.pubstructParallelProcessor{data:Vec<u64>,}implParallelProcessor{pubfnnew(size:usize)->Self{Self{data:(0..sizeasu64).collect(),}}/// Parallel map operation.pubfnparallel_map<F>(&self,f:F)->Vec<u64>whereF:Fn(u64)->u64+Sync+Send,{self.data.par_iter().map(|&x|f(x)).collect()}/// Parallel filter operation.pubfnparallel_filter<F>(&self,f:F)->Vec<u64>whereF:Fn(&u64)->bool+Sync+Send,{self.data.par_iter().filter(|&&x|f(&x)).copied().collect()}/// Parallel reduce operation.pubfnparallel_reduce<F>(&self,f:F)->u64whereF:Fn(u64,u64)->u64+Sync+Send,{self.data.par_iter().copied().reduce(||0,f)}/// Parallel sum operation.pubfnparallel_sum(&self)->u64{self.data.par_iter().sum()}/// Parallel sort operation.pubfnparallel_sort(&mutself){self.data.par_sort();}/// Parallel group by operation.pubfnparallel_group_by<F,K>(&self,key_fn:F)->HashMap<K,Vec<u64>>whereF:Fn(&u64)->K+Sync+Send,K:std::hash::Hash+Eq+Send,{self.data.par_iter().map(|&x|(key_fn(&x),x)).collect()}}/// Demonstrates parallel processing with custom thread pool.pubstructCustomThreadPool{workers:Vec<thread::JoinHandle<()>>,job_sender:mpsc::Sender<Job>,}typeJob=Box<dynFnOnce()+Send+'static>;implCustomThreadPool{pubfnnew(size:usize)->Self{let(job_sender,job_receiver)=mpsc::channel();letjob_receiver=Arc::new(Mutex::new(job_receiver));letmutworkers=Vec::with_capacity(size);foridin0..size{letjob_receiver=Arc::clone(&job_receiver);letworker=thread::spawn(move||{loop{letjob=job_receiver.lock().unwrap().recv();matchjob{Ok(job)=>{println!("Worker {} executing job",id);job();}Err(_)=>{println!("Worker {} shutting down",id);break;}}}});workers.push(worker);}Self{workers,job_sender}}pubfnexecute<F>(&self,f:F)whereF:FnOnce()+Send+'static,{letjob=Box::new(f);self.job_sender.send(job).unwrap();}}implDropforCustomThreadPool{fndrop(&mutself){drop(&self.job_sender);forworkerinself.workers.drain(..){worker.join().unwrap();}}}/// Demonstrates parallel processing with work stealing.pubstructWorkStealingProcessor{data:Vec<u64>,chunk_size:usize,}implWorkStealingProcessor{pubfnnew(data:Vec<u64>,chunk_size:usize)->Self{Self{data,chunk_size}}/// Process data in parallel chunks.pubfnprocess_chunks<F>(&self,f:F)->Vec<u64>whereF:Fn(&[u64])->Vec<u64>+Sync+Send,{self.data.par_chunks(self.chunk_size).map(f).flatten().collect()}/// Process data with work stealing.pubfnprocess_with_work_stealing<F>(&self,f:F)->Vec<u64>whereF:Fn(u64)->u64+Sync+Send,{self.data.par_iter().map(|&x|f(x)).collect()}/// Process data with load balancing.pubfnprocess_with_load_balancing<F>(&self,f:F)->Vec<u64>whereF:Fn(u64)->u64+Sync+Send,{self.data.par_iter().with_min_len(1).map(|&x|f(x)).collect()}}/// Demonstrates parallel processing with synchronization.pubstructSynchronizedProcessor{data:Arc<Mutex<Vec<u64>>>,results:Arc<Mutex<Vec<u64>>>,}implSynchronizedProcessor{pubfnnew(data:Vec<u64>)->Self{Self{data:Arc::new(Mutex::new(data)),results:Arc::new(Mutex::new(Vec::new())),}}/// Process data with synchronization.pubfnprocess_synchronized<F>(&self,f:F)->Vec<u64>whereF:Fn(u64)->u64+Sync+Send,{letdata=self.data.lock().unwrap();letresults:Vec<u64>=data.par_iter().map(|&x|f(x)).collect();results}/// Process data with atomic operations.pubfnprocess_atomic<F>(&self,f:F)->Vec<u64>whereF:Fn(u64)->u64+Sync+Send,{letdata=self.data.lock().unwrap();letresults:Vec<u64>=data.par_iter().map(|&x|f(x)).collect();results}}#[cfg(test)]modtests{usesuper::*;#[test]fntest_parallel_processor(){letprocessor=ParallelProcessor::new(1000);letresults=processor.parallel_map(|x|x*2);assert_eq!(results.len(),1000);letfiltered=processor.parallel_filter(|&x|x%2==0);assert!(filtered.len()>0);letsum=processor.parallel_sum();assert!(sum>0);}#[test]fntest_work_stealing_processor(){letdata=(0..1000).collect();letprocessor=WorkStealingProcessor::new(data,100);letresults=processor.process_chunks(|chunk|{chunk.iter().map(|&x|x*2).collect()});assert_eq!(results.len(),1000);}#[test]fntest_synchronized_processor(){letdata=(0..100).collect();letprocessor=SynchronizedProcessor::new(data);letresults=processor.process_synchronized(|x|x*2);assert_eq!(results.len(),100);}}