Is is possible to use callback pattern in multi threaded context?

i have the following function

    pub fn start(
        self: Arc<Self>,
        addr: &str,
        control_fn: fn(String) -> bool,
    ) -> std::io::Result<()>

which does

                if !control_fn(tkn.to_owned()) {
                    let _ = sock.write(b"invalid token\r\n");
                    continue;
                }

in another thread.

when I try to call it in the app

    let (_state, app_state) = crate::init::init_cache(streamer.clone());
    fn check_tkn(token: String) -> bool {
        let uid_token: Vec<&str> = token.split("__").collect();
        if uid_token.len() != 2 {
            false
        } else {
            check_token(uid_token[0], uid_token[1], app_state).is_ok()
        }
    }
    streamer
        .clone()
        .start(&streamer_addr, check_tkn)
        .expect("cannot start streamer");

I get all sorts of errors. All I want is simply to check the given token and return bool I cant use closures because apparently closures are not Send I also cannot use function pointers because they cannot use the environment around I also cannot use factory function to capture environment because again the inner function cannot be sent between threads or cannot capture the outer functions environment.
all I want is

fn do_something(...,check(String)->bool){
...    
    if ! check(data){
        return
    }
}

Did you try an argument like this?

    check: impl Fn(String) -> bool + Send,

It could be relaxed to FnMut if you're only going to use it in one thread at a time, and further to FnOnce if you're only going to call it once.

(Idiomatically that should take &str, unless it needs to manipulate the actual allocation.)

1 Like

well I would like to take s &str but then I run into whole bunch of lifetime issues and stuff so I gave up on that

This is not true in general. Closures are only not Send if they capture something by value or mut reference that is not Send, or if they capture something by shared reference that is not Sync.

You are trying to use app_state in your callback. I don’t know what type that value has. Judging by your use case, check_token(/* ... */, app_state), a closure would capture app_state by value/move. This would also mean (as an additional difficulty next to the question of Send/Sync) that unless app_state implements Copy (which it would for example if it is already a reference) your closure will only be callable once, so it could only be FnOnce.

If you need more help you should probably provide more information, especially regarding app_state, or perhaps even a complete example.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.