Hi there it's my first time here so apologies for mistakes about the language, I'm still learning it
With that said, I'm also a beginner at multi-threaded applications so I may have the wrong concepts in my head about the structures I'm trying to use
My task is to create a simple multi threaded particle simulation, to start with, I create a threadpool to manage the movement of particles, and another for the collision detection + response.
The current structure looks like this:
- Movement manager clones + locks a strip of the array
- Movement manager does their stuff on the particle strip
- Movement manager releases the lock and sends a message to the Collision manager, giving the index of the strip that is now free to be processed
- Movement repeats this for all strips
- Collision receives the index, clones + locks the arc strip data and does the collision detection + response (inverting x,y,z velocity on a particle if it exceeds the bounds)
When running with a strip size of 1, this works fine, however, when I try upping the strip count to 2+ , it leads to unclear results, where particles will completely ignore their bounds and simply keep moving.
It is almost as if the collision manager's changes to the velocity go unnoticed by the movement manager in the next frame of the simulation. I have been scratching my head for a few hours at this as I don't see why the changes aren't being kept, I understand that Arcs have a shared memory location, and therefore any changes made to a strip in one thread should persist into the other?
let strips = Arc::new( vec! [ Arc::new( Mutex::new ( vec![ particle;1 ] ) ); 2 ] );
This is my top-level code for creating the strips of particles
let move_particles = strips.clone();
let collision_particles = strips.clone();
...
let (tmc, rmc) : (Sender<usize>, Receiver<usize>)= mpsc::channel();
...
let collision_manager = Arc::new(CollisionManager::new(width, depth, collision_particles));
let collision_join_handle = std::thread::spawn(move || CollisionBeginListening(collision_manager, rmc));
let movement_manager = MovementManager::new(tmc, move_particles);
Movement Manager
threadpool.scoped(|scope|{
for i in 0..2{ //2 = number of strips
let strip = self.particles[i].clone();
scope.execute(move || move_function(strip));
scope.join_all();
self.transmitter.send(i).unwrap();
}
});
move_function
let mut particles = strip.lock().unwrap();
for i in 0..particles.len(){
let vel = particles[i].get_velocity();
particles[i].move_particle();
}
Collision Manager
threadpool.scoped(|scope|{
loop{
let index = receiver.recv().unwrap();
let strip = cm.particles[index].clone();
scope.execute(move || collide_function(strip, width, depth));
scope.join_all();
}
});
collide_function
let mut particles = strip.lock().unwrap();
for i in 0..particles.len(){
let pos = particles[i].get_position();
if pos[0] > 0.5 || pos[0] < -0.5{
particles[i].invert_x_velocity();
}
if pos[1] < 0.0 || pos[1] > 2.0{
particles[i].invert_y_velocity();
}
if pos[2] > 0.5 || pos[2] < -0.5{
particles[i].invert_z_velocity();
}
}
Any help is appreciated because I'm stuck in a rut of not understanding, many thanks