Kenkron
Kenkron

Reputation: 573

In Rust, how do you pass a function with a mutable parameter to be used in parllel?

I've been playing around with collision detection, and I've been working on a function that collides two sets of objects with each other. To allow it to be run in parallel, only the first set is mutable, and the elements of the first set are iterated through with rayon.

All of that seems to be fine, except that I want to be able to pass a collision resolution function. Because its first argument is a mutable reference, Rust also seems to want the function itself to be mutable. This doesn't work if I want the function to run in parallel.

pub fn collide_with_binned_static<T1: Send + Sync, T2: Send + Sync>(
    items_a: &mut [T1],
    aabb: impl Fn(&T1) -> Rect + Send + Sync,
    items_b: &[T2],
    bin_index_b: &BinIndex,
    f: impl FnMut(&mut T1, &T2) + Send + Sync)
{
    items_a.par_iter_mut().for_each(|item_a| {
        let collisions = bin_index_b.check_rect_collision(&aabb(item_a));
        for collision in collisions {
            f(&mut *item_a, &items_b[collision]);
//          ^ cannot borrow as mutable
        }
    });
}

Basically, I don't see how a function that takes mutable items needs to be mutable itself. If I was calling a static function with static types, instead of a generic function with generic types, I'm confident this would work. Is there anything I can do to fix it?

Upvotes: 0

Views: 232

Answers (2)

Kenkron
Kenkron

Reputation: 573

I thought I was using a function reference, which would have worked.

f: fn(&mut T1, &T2)

Instead I was using a closure, which could have mutated state in its scope, allowing previous calls to affect subsequent calls.

Upvotes: 1

cafce25
cafce25

Reputation: 27549

What needs mutable access is calling a FnMut a closure allowed to mutate it's captures but if your closure doesn't need mutable access to it's envirnoment that's not necessary, you can take a Fn or a function pointer fn instead and it should work.

Upvotes: 0

Related Questions