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
) -> (
tokio::task::JoinHandle<()>,
tokio::sync::mpsc::UnboundedSender<Item>,
)
where
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 {
f(item).await;
});
}
});
(service, tx)
}
As an async and Rust beginner I'm confused by these:
- why does
f
need to bemut
? Why modifies it? - 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.
Thank you!