Skip to content
New issue

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

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

Already on GitHub? # 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 &'_ …
    }
}

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

Successfully merging a pull request may close this issue.

5 participants