logo
Tags down

shadow

Share function reference between threads in Rust


By : user6096065
Date : September 16 2020, 06:00 AM
this one helps.
A function has a static address during the runtime of the program, therefore I can't see a problem here.
code :
fn do_sth_multithreaded(transform_fn: &'static (dyn Fn(&String) -> String + Sync))


Share : facebook icon twitter icon

What do I use to share an object with many threads and one writer in Rust?


By : Erika
Date : March 29 2020, 07:55 AM
it fixes the issue Rust has a built-in concurrency primitive exactly for this task called RwLock. Together with Arc, it can be used to implement what you want:
code :
use std::sync::{Arc, RwLock};
use std::sync::mpsc;
use std::thread;

const N: usize = 12;

let shared_data = Arc::new(RwLock::new(Vec::new()));
let (finished_tx, finished_rx) = mpsc::channel();

for i in 0..N {
    let shared_data = shared_data.clone();
    let finished_tx = finished_tx.clone();
    if i % 4 == 0 {
        thread::spawn(move || {
            let mut guard = shared_data.write().expect("Unable to lock");
            guard.push(i);
            finished_tx.send(()).expect("Unable to send");
        });
    } else {
        thread::spawn(move || {
            let guard = shared_data.read().expect("Unable to lock");
            println!("From {}: {:?}", i, *guard);
            finished_tx.send(()).expect("Unable to send");
        });
    }
}

// wait until everything's done
for _ in 0..N {
    let _ = finished_rx.recv();
}

println!("Done");

Lifetime of function reference in Rust


By : PingPing
Date : March 29 2020, 07:55 AM
wish helps you A few things:
You used &Fn() instead of fn(). The former is a trait object of the Fn trait, the latter is a good ol' function pointer. While the former is more general (in particular, it supports closures), it's rather unusual to store a reference to a closure that lives somewhere else. Therefore, if you want to store closures as well, you'd probably use a Box which solves your lifetime problems. If you don't care about closures, but just want to save function pointer, you can simply write Visual(fn(Entity)),. Function pointer always have a static lifetime. So this solves your lifetime problems as well. But what if you really want to store a reference to an Fn trait object, which lives somewhere else? The solution depends on where it lives: In Entity: see here somehere else: use a lifetime <'a> You wrote Fn(Entity) -> (). The -> () is always useless, you can omit it.

Rust Mutex is not working when using a callback function from multiple C threads created by `fork`


By : user2579235
Date : March 29 2020, 07:55 AM
fixed the issue. Will look into that further The Cuba C library has this to say:
code :
use nix::unistd::{fork, ForkResult}; // 0.13.0
use std::{sync::Mutex, thread, time::Duration};

fn main() {
    let shared = Mutex::new(10);

    match fork() {
        Ok(ForkResult::Parent { .. }) => {
            let max = shared.lock().unwrap();
            for _ in 0..*max {
                println!("Parent");
                thread::sleep(Duration::from_millis(10));
            }
        }
        Ok(ForkResult::Child) => {
            let max = shared.lock().unwrap();
            for _ in 0..*max {
                println!("Child");
                thread::sleep(Duration::from_millis(10));
            }
        }
        Err(e) => {
            eprintln!("Error: {}", e);
        }
    }
}
$ cargo run

Parent
Child
Parent
Child
Child
Parent
Child
Parent
Child
Parent
Child
Parent
Child
Parent
Child
Parent
Child
Parent
Child
Parent
#[macro_use]
extern crate slog;

use slog::Drain;

fn integrand(loggers: &mut Vec<slog::Logger>, core: i32) {
    info!(loggers[core as usize], "A\nB\nC\n{}", core);
}

fn main() {
    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::CompactFormat::new(decorator).build();
    let drain = std::sync::Mutex::new(drain).fuse();

    let log = slog::Logger::root(drain, o!());

    let logs = vec![log.clone(); 11];

    cuba_repro(logs, integrand);
}

use std::{ffi::c_void, thread};

type Integrand<T> = fn(&mut T, i32);

fn cuba_repro<T>(mut user_data: T, mut integrand: Integrand<T>) {
    // From the `vegas` method
    let user_data_ptr = &mut user_data as *mut _ as *mut c_void;
    let integrand_ptr = &mut integrand as *mut _ as *mut c_void;

    unsafe { cuba_repro_ffi::<T>(user_data_ptr, integrand_ptr) }
}

unsafe fn cuba_repro_ffi<T>(user_data: *const c_void, integrand: *const c_void) {
    let user_data = FfiDoesNotCareAboutSendOrSync(user_data);
    let integrand = FfiDoesNotCareAboutSendOrSync(integrand);

    let threads: Vec<_> = (0..4).map(move |i| {
        thread::spawn(move || {
            // C doesn't care about this pedantry
            let user_data = &mut *(user_data.0 as *const T as *mut T);
            let integrand = &mut *(integrand.0 as *const Integrand<T> as *mut Integrand<T>);

            // From the `c_integrand` function
            let k: &mut T = &mut *(user_data as *mut _);
            let _ignored = integrand(k, i);
        })
    }).collect();

    for t in threads { t.join().unwrap() }
}

#[derive(Copy, Clone)]
struct FfiDoesNotCareAboutSendOrSync<T>(T);
unsafe impl<T> Send for FfiDoesNotCareAboutSendOrSync<T> {}
unsafe impl<T> Sync for FfiDoesNotCareAboutSendOrSync<T> {}

Is this the idiomatic way to share a closure callback among threads in rust?


By : Solomon
Date : March 29 2020, 07:55 AM
I wish did fix the issue. Let me rewrite the interesting pieces of code, as I understand the idiomatic Rust:
First, the LibThreaded::new can be easily rewritten with a call to unwrap_or_else:
code :
pub fn new(callback: Option<Callback>) -> LibThreaded {
    LibThreaded {
        something_threaded: "I am in a thread: ".to_string(),
        callback: callback.unwrap_or_else(|| Arc::new(Mutex::new(|_,_| {})))
    }
}
pub async fn set_callback(&mut self, callback: Option<impl FnMut(String, String) + Send + Sync + 'static>) {
    let callback = callback.map(|cb| Arc::new(Mutex::new(cb)) as Callback); //line 1
    if let Some(cb) = &callback {  //line 2
        self.callback = cb.clone();
        let c = &mut *self.callback.lock().unwrap();
        (c)(self.something.clone(), "hello world".to_string());
    }
    let mut t = LibThreaded::new(callback);

    //...
}

Rust - Pass a function reference to threads


By : user3520964
Date : March 29 2020, 07:55 AM
Hope that helps In order to send an Arc to another thread, the Arc needs to implement Send. If you look at the docs for Arc you can see that it has
code :
impl<T> Send for Arc<T> where
    T: Send + Sync + ?Sized {}
pub struct MyStruct {
    f: Arc<dyn Fn(Vec<f64>) -> Vec<f64> + Sync + Send>,
}

impl MyStruct {
   pub fn new(f: Arc<dyn Fn(Vec<f64>) -> Vec<f64> + Sync + Send>) -> MyStruct {
      MyStruct { f }
   }
   // ...
}
shadow
Privacy Policy - Terms - Contact Us © 35dp-dentalpractice.co.uk