Hi,
I'm having a bit of trouble understanding how I can make futures work with mutexes.
Let's say I have the following structure:
struct Kitchen { /** */ }
impl Kitchen {
/* Imagine potentially many functions here for things you could do in a kitchen */
/// Makes a cheesecake. Can take some time.
pub async fn make_cheesecake(&mut self) {
/** */
}
/// Will wait until there is a cheesecake to eat
pub async fn eat_cheesecake(&mut self) {
/** */
}
}
And several actors that may access this kitchen, but they all need exclusive access (there's only one sink, one burner, or whatever). Actors all have Arc references to the workplace, and because they need mutability, they get an Arc<Mutex<Workplace>>
over it.
Each actor runs as it own task that gets scheduled by the landlord which is a custom Executor
of sorts here (keeps track of all tasks, and polls through them in some obscure way).
So let's say I have actor 1 that says:
async fn actor1(kitchen_ref: Arc<Mutex<Kitchen>>) {
/* */
kitchen.lock().make_cheesecake().await;
/* */
}
And actor 2 that does the counterpart:
async fn actor2(kitchen_ref: Arc<Mutex<Kitchen>>) {
/* */
kitchen.lock().eat_cheesecake().await;
/* */
}
Let's now say that actor2 gets executed first. If I understand correctly, it will take the lock for the kitchen, and therefore keep a mutexguard for the kitchen in the fields of the newly created impl Future
(return type of eat_cheesecake). Now actor1 gets executed, it tries to acquire the lock, and it fails. Actor2 gets executed again, can't eat any cheesecake, returns. Actor1 again, etc. Seems like a deadlock.
What I would like is that each time the Future is polled, it tries to acquire the lock. If it fails, it returns Pending. Otherwise, it returns the result of the poll. But in any case, it should not acquire the lock for the entire waiting time, only during the call to poll()
. This would allow actor1 to run as expected and make that delicious cheesecake.
I've seen that futures_util
offers some futures-aware Mutex
, but I am under the impression that it would be the same. I would have something like kitchen.lock().await.eat_cheesecake().await;
but the actor1 would still wait forever since actor2 still keeps the mutex once it acquired it (or so it seems to me).
Is there something I missed or misunderstood about futures and mutexes? If not, do you have any idea on how I could proceed to make both actors happy?
I hope the culinary MRE was clear