Skip to content

Add Mutex::poll_lock method #1972

@canndrew

Description

@canndrew

I just had a bug in some code that looks like this:

use futures::lock::Mutex;

struct MySender {
    inner: Arc<Mutex<Inner>>,
}

struct MyReceiver {
    inner: Arc<Mutex<Inner>>,
}

impl Future for MyReceiver {
    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
        if let Poll::Ready(inner) = Pin::new(&mut self.get_mut().inner.lock()).poll(cx) {
            // do some stuff
            return Poll::Ready(());
        }
        Poll::Pending
    }
}

The bug is that the MutexLockFuture returned by Mutex::lock deregisters itself when it gets dropped. So if I poll MyReceiver and the lock is held the task won't get woken up again when the lock is released. AFAICT my options for fixing this are:

  1. Store the MutexLockFuture inside MyReceiver. This is inconvenient and inefficient since MutexLockFuture borrows the Mutex and so I'd need to use rental and an extra layer of boxing.
  2. Implement MyReceiver with an async block/function instead of implementing Future directly. Again this means an extra layer of boxing. Also I'm trying to implement a low-level primitive here and I'd rather just implement Future directly.
  3. Use a std non-async Mutex. This is obviously less than ideal, though I know in my case the lock won't get held for very long.

At the moment I've gone for option (2) since it's the laziest option, but it would be nice if there was a simple way to do this properly.

Could we add a poll_lock method to Mutex which allows me to use the Mutex in the buggy way I attempted above?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions