Home > Blockchain >  Multithreading with a Vector of different functions
Multithreading with a Vector of different functions

Time:05-09

I am trying to run multiple functions on different threads. I wrote this (minimal) code that works

use std::thread;

fn f1(count: usize) {
    for i in 0..count { /*do something*/ }
}

fn f2(count: usize) {
    for i in 0..count { /*do something*/ }
}

fn run(ops: &Vec<impl Fn(usize)   Sync   Send   Copy   'static>) {
    for i in 0..ops.len() {
        let func = ops[i];
        thread::spawn(move || func(1000));
    }
}

fn main() {
    let ops = vec![f1, f1]; // putting the same function twice
    run(&ops);
}

However, as soon as I send different functions

    let ops = vec![f1, f2];

Compiling fails. As I understand it, I cannot hold different types in the same vector (I guess, functions have different memory requirements, though I'm not quite sure how function pointers work).

I tried browsing similar questions on SO, and I tried this solution

    let ops: Vec<&dyn Fn(usize)> = vec![&f1, &f2];

and I get this error

`dyn Fn(usize)` cannot be shared between threads safely
the trait `Sync` is not implemented for `dyn Fn(usize)`

And I'm stuck as I'm struggling to understand the base issue. Do you have insights on how I should understand this problem, and any pointers on how to solve it ?

Thank you!

CodePudding user response:

Just as you can add the Sync marker with impl, you can also add it with &dyn, but you may need parenthesis to disambiguate:

fn run(ops: &Vec<&'static (dyn Fn(usize)   Sync)>)

Two minor comments:

  • Generally, using &[…] instead of &Vec<…> is more flexible and to be preferred.
  • No need to do for i in 0…foos.len() in rust, for foo in foos will do fine. (You may occasionally have to use for foo in &foos or for foo in foos.iter(). If you do need the index, .enumerate() is convenient.)
  • If the 'static is a bother (e.g. because you want to pass in some closure that captures local variables and can't be 'static), you could either use scoped threads (example), or pass owned Fns as Vec<Box<dyn Fn(usize) Sync>>.
  • Related