I'm curious about people's opinions on Future
providing an assurance of completion, perhaps via an additional Complete
auto trait (for example).
As background, I've been thinking recently about async/await and its applicability to actor models. In particular, I've been thinking about whether an actor's receiver should be an async function. An actor's receiver provides the ability for it to receive messages from its mailbox (aka a channel). An example without async:
struct Greet {
whom: String,
}
struct HelloWorld {}
impl Actor<Greet> for HelloWorld {
fn receive(&mut self, context: &mut ActorContext<Greet>, message: &Greet) {
println!("Hello {}!", message.whom);
}
}
With an async receiver, the above could be adapted to invoke some async function:
#[derive(Clone)]
struct Greet {
whom: String,
}
struct HelloWorld {}
impl HelloWorld {
async fn hello_world(message: &Greet) {
println!("Hello {}!", message.whom)
}
}
impl Actor<Greet> for HelloWorld {
fn receive(&mut self, _context: &mut ActorContext<Greet>, message: &Greet) -> Pin<Box<dyn Future<Output=()> + Complete + '_>> {
let m = message.to_owned();
Box::pin(async move {
HelloWorld::hello_world(&m).await
})
}
}
A concern when considering async/await receivers is that an awaited future may block indefinitely. The consequence of this is that an actor is not able to process any subsequent message; one such message being to request termination. For actor receivers then, I've been wondering about a new trait to be used in combination with Future
to assure the compiler that the async code should always complete. Perhaps signatures then become something like Future<Output = ???> + Complete
(in the spirit of how + Send
is used). Perhaps the compiler can then ensure that async functions must also convey that they can complete.
Perhaps completion-assured futures might benefit other use-cases. Or perhaps there's room in the existing Future API to simply state that it should always complete by way of a convention.
Thoughts?