Using a callback FnMut in multiple tokio::tasks

I have a function that spawns a tokio::task for processing incoming items sent by UnboundedSender. The goal is to call a user-supplied function f that is called for each item. Each invocation of f is inside a nested task.

This is is what I've come up with so far. It might look a bit contrived but I have removed irrelevant bits -- the actual code has additional logic:

pub fn spawn<Item, F, Fut>(
    mut f: F, // <--- MUTABLE
) -> (
    Item: Send + 'static, // <--- STATIC
    F: FnMut(Item) -> Fut + Send + Copy + 'static,
    Fut: futures_core::Future<Output = ()> + Send + 'static,
    let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<Item>();

    let service = tokio::spawn(async move {
        while let Some(item) = rx.recv().await {
            tokio::spawn(async move {

    (service, tx)

As an async and Rust beginner I'm confused by these:

  1. why does f need to be mut? Why modifies it?
  2. the compiler told me to make Item 'static although I'm not quite sure why in this case. Am I limiting myself by restricting to 'static items?

I'm sure there's a better way in general, this is my first attempt at making a function like this. I'm open to suggestions although I'd like to understand how this particular code can be improved. :slight_smile:

Thank you!

Calling an FnMut will mutate the closure, so that's why you need to mark it as mutable.

As for the Item, yes you are limiting yourself to 'static items. In this context, the Item being 'static means that the value does not contain any (non-static) references, so e.g. String is a 'static type because it doesn't have references inside.

Thank you, 'static makes sense now.

I'm still puzzled about the mutable FnMut -- is it because the closure can contain mutable data/references? Can FnMut ever be non-mut?

Regarding FnMut

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.