Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider allowing owned data in MappedMutexGuard #289

Open
eira-fransham opened this issue Jun 21, 2021 · 6 comments · May be fixed by #290
Open

Consider allowing owned data in MappedMutexGuard #289

eira-fransham opened this issue Jun 21, 2021 · 6 comments · May be fixed by #290

Comments

@eira-fransham
Copy link

There is no reason that MappedMutexGuard needs to contain a *mut T, it can just contain a T. I believe that you may have to change the bound of map like so:

pub fn map<U: ?Sized + 'a, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
where
    F: FnOnce(&'a mut T) -> U,
{
    let raw = &s.mutex.raw;
    let data = f(unsafe { &mut *s.mutex.data.get() });
    mem::forget(s);
    MappedMutexGuard {
        raw,
        data,
        marker: PhantomData,
    }
}

And you should also bound MappedMutexGuard's T parameter by 'a. This is strictly more general than the existing method, but will break anyone who explicitly specifies the T parameter of MappedMutexGuard. To get around this, you could rename MappedMutexGuard to OwnedMappedMutexGuard and make the original name a type alias like so:

pub type MappedMutexGuard<'a, R, T> = OwnedMappedMutexGuard<'a, R, &'a mut T>;
@eira-fransham eira-fransham linked a pull request Jun 21, 2021 that will close this issue
@xmo-odoo
Copy link

Is the consideration any different for the mapped RwLock guards?

I recently hit this issue because I wanted to keep the guard around a structure which borrows stored data, but is not such itself, but the current signature forbids such.

@Amanieu
Copy link
Owner

Amanieu commented Nov 26, 2021

Yes, rhe same issue described in the PR also applies to RwLock.

@xmo-odoo
Copy link

Yes, rhe same issue described in the PR also applies to RwLock.

Guessing you mean your objection on usability grounds in #290? I was mostly wondering if there were additional unsafety / concerns which would make the issue even more problematic for RwLock than it is for Mutex or if it was essentially the same, sorry for not being clear.

@Amanieu
Copy link
Owner

Amanieu commented Nov 26, 2021

I think it's essentially the same.

@Ralith
Copy link

Ralith commented May 26, 2023

I ran into this today on RwLock. I want to maintain (roughly) a RwLock<Vec<Mutex<T>> so that individual Ts can be mutated concurrently, locking the whole thing only when adding/removing values, and I want to encapsulate this with an API that returns a smart pointer analogous to MutexGuard, which is internally a RwLockReadGuard<'_, MutexGuard<'_, T>>. However, RwLockReadGuard::map's current signature makes this impossible.

@qsantos
Copy link

qsantos commented Nov 27, 2023

I encountered this as well. Essentially, I need to implement iteration on a type Y that wraps a type X. Instead of reimplementing iteration from scratch, I could wrap the iteration over X by doing the following:

struct Iter<'a>(X::Iter<'a>);

impl<'a> Iterator for Iter<'a> {
    type Item = &'a YElem;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|x_elem| &x_elem.y_elem)
    }
}

impl Y {
    fn iter(&self) -> Iter<'_> {
        let guard = self.lock.read();
        Iter(RwLockReadGuard::map(guard, |x| x.iter())) // here, we need to return Iter<'_>, not &'_ …
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants