Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to pass a function as parameter for thread?

I’m a new rustacean and I try to pass a function as argument in another function in order to create threads with the function pass as argument.

Here the code :

use std::os::unix::net::{UnixListener, UnixStream};
use std::thread;
use std::io::Read;
use anyhow::Context;

pub struct SocketServer {
    path: String,
    listener: UnixListener,
}

impl SocketServer {
    pub fn new(path: &str) -> anyhow::Result<SocketServer>{

        if std::fs::metadata(path).is_ok() {
            println!("A socket is already present. Deleting...");
            std::fs::remove_file(path).with_context(|| {
                format!("could not delete previous socket at {:?}", path)
            })?;
        }

        let socket_listener =
            UnixListener::bind(path).context("Could not create the unix socket")?;

        let path = path.to_string();

        Ok(SocketServer{ path, listener: socket_listener })
    }

    pub fn start(&self, f: &dyn Fn(UnixStream)) -> anyhow::Result<()>{

        for stream in self.listener.incoming() {
            match stream {
                Ok(stream) => {
                    thread::spawn(||f(stream));
                }
                Err(err) => {break;}
            }
        }
        Ok(())
    }
}

pub fn handle_stream(mut unix_stream: UnixStream) -> anyhow::Result<()> {
    let mut message = String::new();
    unix_stream
        .read_to_string(&mut message)
        .context("Failed at reading the unix stream")?;

    println!("We received this message: {}", message);

    Ok(())
}

Here the error I get when in try to compile :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

error[E0277]: `dyn Fn(UnixStream)` cannot be shared between threads safely
   --> src/socket.rs:34:35
    |
34  |                     thread::spawn(||f(stream));
    |                     ------------- ^^^^^^^^^^^ `dyn Fn(UnixStream)` cannot be shared between threads safely
    |                     |
    |                     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `dyn Fn(UnixStream)`
    = note: required for `&dyn Fn(UnixStream)` to implement `Send`

I got some information in the Rust book but I still don’t understand wich function need to implement what.
Can you give me some hints? (Advices on other part are welcome too )

I tried to remove closure but it goes to another error :

error[E0277]: expected a `FnOnce<()>` closure, found `()`
   --> src/socket.rs:34:35
    |
34  |                     thread::spawn(f(stream));
    |                     ------------- ^^^^^^^^^ expected an `FnOnce<()>` closure, found `()`
    |                     |
    |                     required by a bound introduced by this call
    |
    = help: the trait `FnOnce<()>` is not implemented for `()`
    = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `spawn`
   --> /rust/lib/rustlib/src/rust/library/std/src/thread/mod.rs:661:8
    |
661 |     F: FnOnce() -> T,
    |        ^^^^^^^^^^^^^ required by this bound in `spawn`

>Solution :

Is there a reason you need a dyn Fn?
The easiest is probably to accept a impl Fn(UnixStream) + Send + Clone + 'static instead

pub fn start<F>(&self, f: F) -> anyhow::Result<()>
where
    F: Fn(UnixStream) + Send + Clone + 'static,
{
    for stream in self.listener.incoming() {
        let f = f.clone();
        match stream {
            Ok(stream) => {
                thread::spawn(move || f(stream));
            }
            Err(err) => break,
        }
    }
    Ok(())
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading