From bd6cd5eacc7ad61b78513bacd088c4fc1c9d0377 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 4 Oct 2023 01:30:33 -0700 Subject: [PATCH] worker module --- src/body.rs | 2 +- src/main.rs | 1 + src/worker.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/worker.rs diff --git a/src/body.rs b/src/body.rs index 71f089f..6e4727c 100644 --- a/src/body.rs +++ b/src/body.rs @@ -34,7 +34,7 @@ pub enum InputInstruction { //for interpolation / networking / playback reasons, most playback heads will always want //to be 1 instruction ahead to generate the next state for interpolation. } - +#[derive(Clone,Debug)] pub struct Body { position: glam::Vec3,//I64 where 2^32 = 1 u velocity: glam::Vec3,//I64 where 2^32 = 1 u/s diff --git a/src/main.rs b/src/main.rs index 0fab7fe..053279d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ mod framework; mod primitives; mod instruction; mod load_roblox; +mod worker; struct Entity { index_count: u32, diff --git a/src/worker.rs b/src/worker.rs new file mode 100644 index 0000000..2e457cf --- /dev/null +++ b/src/worker.rs @@ -0,0 +1,84 @@ +use std::thread; +use std::sync::{mpsc,Arc}; +use parking_lot::Mutex; + +//The goal here is to have a worker thread that parks itself when it runs out of work. +//The worker thread publishes the result of its work back to the worker object for every item in the work queue. +//The physics (target use case) knows when it has not changed the body, so not updating the value is also an option. + +struct Worker { + sender: mpsc::Sender, + value:Arc>, +} + +impl Worker { + fn newValue+Send+'static>(value:Value,f:F) -> Self { + let (sender, receiver) = mpsc::channel::(); + let ret=Self { + sender, + value:Arc::new(Mutex::new(value)), + }; + let value=ret.value.clone(); + thread::spawn(move || { + loop { + match receiver.recv() { + Ok(task) => { + println!("Worker got a task"); + // Process the task + let v=f(task);//make sure function is evaluated before lock is acquired + *value.lock()=v; + } + Err(_) => { + println!("Worker stopping.",); + break; + } + } + } + }); + ret + } + + fn send(&self,task:Task)->Result<(), mpsc::SendError>{ + self.sender.send(task) + } + + fn grab_clone(&self)->Value{ + self.value.lock().clone() + } +} + +#[test]//How to run this test with printing: cargo test --release -- --nocapture +fn test_worker() { + println!("hiiiii"); + // Create the worker thread + let worker = Worker::new(crate::body::Body::with_pva(glam::Vec3::ZERO,glam::Vec3::ZERO,glam::Vec3::ZERO), + |_|crate::body::Body::with_pva(glam::Vec3::ONE,glam::Vec3::ONE,glam::Vec3::ONE) + ); + + // Send tasks to the worker + for i in 0..5 { + let task = crate::instruction::TimedInstruction{ + time:0, + instruction:crate::body::PhysicsInstruction::StrafeTick, + }; + worker.send(task).unwrap(); + } + + // Optional: Signal the worker to stop (in a real-world scenario) + // sender.send("STOP".to_string()).unwrap(); + + // Sleep to allow the worker thread to finish processing + thread::sleep(std::time::Duration::from_secs(2)); + + // Send a new task + let task = crate::instruction::TimedInstruction{ + time:0, + instruction:crate::body::PhysicsInstruction::StrafeTick, + }; + worker.send(task).unwrap(); + + println!("value={:?}",worker.grab_clone()); + + // wait long enough to see print from final task + thread::sleep(std::time::Duration::from_secs(1)); +}