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

Tracking Issue for mapped_lock_guards (MappedMutexGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard) #117108

Open
2 of 4 tasks
zachs18 opened this issue Oct 23, 2023 · 4 comments
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@zachs18
Copy link
Contributor

zachs18 commented Oct 23, 2023

Feature gate: #![feature(mapped_lock_guards)]

This is a tracking issue for MappedMutexGuard, MappedRwLockReadGuard, and MappedRwLockWriteGuard.

This adds types analogous to lock_api::MappedMutexGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard) to std::sync, and methods MutexGuard::map and MutexGuard::try_map (same for `RwLock*Guard) to create them

Public API

// std::sync::mutex

pub struct MappedMutexGuard<'mutex, T: ?Sized>;

impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
    pub fn map<U, F>(orig: Self, f: F) -> MappedMutexGuard<'mutex, U>
      where 
        F: FnOnce(&mut T) -> &mut U,
        U: ?Sized;
    pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedMutexGuard<'mutex, U>, Self>
      where 
        F: FnOnce(&mut T) -> Option<&mut U>,
        U: ?Sized;
}

impl<'mutex, T: ?Sized> MappedMutexGuard<'mutex, T> {
    pub fn map<U, F>(orig: Self, f: F) -> MappedMutexGuard<'mutex, U>
      where 
        F: FnOnce(&mut T) -> &mut U,
        U: ?Sized;
    pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedMutexGuard<'mutex, U>, Self>
      where 
        F: FnOnce(&mut T) -> Option<&mut U>,
        U: ?Sized;
}

impl<T: ?Sized> Deref/DerefMut for MappedMutexGuard<'_, T>;
impl<T: ?Sized + Debug/Display> Debug/Display for MappedMutexGuard<'_, T>;
// std::sync::rwlock

pub struct MappedRwLockReadGuard<'rwlock, T: ?Sized>;
pub struct MappedRwLockWriteGuard<'rwlock, T: ?Sized>;

impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
    pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U>
      where 
        F: FnOnce(&T) -> &U,
        U: ?Sized;
    pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self>
      where 
        F: FnOnce(&T) -> Option<&U>,
        U: ?Sized;
}
impl<'rwlock, T: ?Sized> MappedRwLockReadGuard<'rwlock, T> {
    pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'rwlock, U>
      where 
        F: FnOnce(&T) -> &U,
        U: ?Sized;
    pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'rwlock, U>, Self>
      where 
        F: FnOnce(&T) -> Option<&U>,
        U: ?Sized;
}

impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
    pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
      where 
        F: FnOnce(&mut T) -> &mut U,
        U: ?Sized;
    pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
      where 
        F: FnOnce(&mut T) -> Option<&mut U>,
        U: ?Sized;
}
impl<'rwlock, T: ?Sized> MappedRwLockWriteGuard<'rwlock, T> {
    pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockWriteGuard<'rwlock, U>
      where 
        F: FnOnce(&mut T) -> &mut U,
        U: ?Sized;
    pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockWriteGuard<'rwlock, U>, Self>
      where 
        F: FnOnce(&mut T) -> Option<&mut U>,
        U: ?Sized;
}

impl<T: ?Sized> Deref for MappedRwLockReadGuard<'_, T>;
impl<T: ?Sized> Deref/DerefMut for MappedRwLockWriteGuard<'_, T>;
impl<T: ?Sized + Debug/Display> Debug/Display for MappedRwLockReadGuard<'_, T>;
impl<T: ?Sized + Debug/Display> Debug/Display for MappedRwLockWriteGuard<'_, T>;

Steps / History

Unresolved Questions

  • None yet.

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html

@zachs18 zachs18 added C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Oct 23, 2023
bors added a commit to rust-lang-ci/rust that referenced this issue Feb 25, 2024
Implement `MappedMutexGuard`, `MappedRwLockReadGuard`, and `MappedRwLockWriteGuard`.

ACP: rust-lang/libs-team#260
Tracking issue: rust-lang#117108

<details> <summary> (Outdated) </summary>

`MutexState`/`RwLockState` structs

~~Having `sys::(Mutex|RwLock)` and `poison::Flag` as separate fields in the `Mutex`/`RwLock` would require `MappedMutexGuard`/`MappedRwLockWriteGuard` to hold an additional pointer, so I combined the two fields into a `MutexState`/`RwLockState` struct. This should not noticeably affect perf or layout, but requires an additional field projection when accessing the former `.inner` or `.poison` fields (now `.state.inner` and `.state.poison`).~~ If this is not desired, then `MappedMutexGuard`/`MappedRwLockWriteGuard` can instead hold separate pointers to the two fields.

</details>

The doc-comments are mostly copied from the existing `*Guard` doc-comments, with some parts from `lock_api::Mapped*Guard`'s doc-comments.

Unresolved question: Are more tests needed?
bors added a commit to rust-lang/miri that referenced this issue Feb 25, 2024
Implement `MappedMutexGuard`, `MappedRwLockReadGuard`, and `MappedRwLockWriteGuard`.

ACP: rust-lang/libs-team#260
Tracking issue: rust-lang/rust#117108

<details> <summary> (Outdated) </summary>

`MutexState`/`RwLockState` structs

~~Having `sys::(Mutex|RwLock)` and `poison::Flag` as separate fields in the `Mutex`/`RwLock` would require `MappedMutexGuard`/`MappedRwLockWriteGuard` to hold an additional pointer, so I combined the two fields into a `MutexState`/`RwLockState` struct. This should not noticeably affect perf or layout, but requires an additional field projection when accessing the former `.inner` or `.poison` fields (now `.state.inner` and `.state.poison`).~~ If this is not desired, then `MappedMutexGuard`/`MappedRwLockWriteGuard` can instead hold separate pointers to the two fields.

</details>

The doc-comments are mostly copied from the existing `*Guard` doc-comments, with some parts from `lock_api::Mapped*Guard`'s doc-comments.

Unresolved question: Are more tests needed?
lnicola pushed a commit to lnicola/rust-analyzer that referenced this issue Apr 7, 2024
Implement `MappedMutexGuard`, `MappedRwLockReadGuard`, and `MappedRwLockWriteGuard`.

ACP: rust-lang/libs-team#260
Tracking issue: rust-lang/rust#117108

<details> <summary> (Outdated) </summary>

`MutexState`/`RwLockState` structs

~~Having `sys::(Mutex|RwLock)` and `poison::Flag` as separate fields in the `Mutex`/`RwLock` would require `MappedMutexGuard`/`MappedRwLockWriteGuard` to hold an additional pointer, so I combined the two fields into a `MutexState`/`RwLockState` struct. This should not noticeably affect perf or layout, but requires an additional field projection when accessing the former `.inner` or `.poison` fields (now `.state.inner` and `.state.poison`).~~ If this is not desired, then `MappedMutexGuard`/`MappedRwLockWriteGuard` can instead hold separate pointers to the two fields.

</details>

The doc-comments are mostly copied from the existing `*Guard` doc-comments, with some parts from `lock_api::Mapped*Guard`'s doc-comments.

Unresolved question: Are more tests needed?
RalfJung pushed a commit to RalfJung/rust-analyzer that referenced this issue Apr 27, 2024
Implement `MappedMutexGuard`, `MappedRwLockReadGuard`, and `MappedRwLockWriteGuard`.

ACP: rust-lang/libs-team#260
Tracking issue: rust-lang/rust#117108

<details> <summary> (Outdated) </summary>

`MutexState`/`RwLockState` structs

~~Having `sys::(Mutex|RwLock)` and `poison::Flag` as separate fields in the `Mutex`/`RwLock` would require `MappedMutexGuard`/`MappedRwLockWriteGuard` to hold an additional pointer, so I combined the two fields into a `MutexState`/`RwLockState` struct. This should not noticeably affect perf or layout, but requires an additional field projection when accessing the former `.inner` or `.poison` fields (now `.state.inner` and `.state.poison`).~~ If this is not desired, then `MappedMutexGuard`/`MappedRwLockWriteGuard` can instead hold separate pointers to the two fields.

</details>

The doc-comments are mostly copied from the existing `*Guard` doc-comments, with some parts from `lock_api::Mapped*Guard`'s doc-comments.

Unresolved question: Are more tests needed?
@Fuuzetsu
Copy link

Is there anything needed to start FCP? Seems it's all implemented and just waiting around.

@Earthcomputer
Copy link

Is there anything needed to start FCP? Seems it's all implemented and just waiting around.

I think it's this, there has been activity on zulip about this since that comment.

@RaitoBezarius
Copy link

From the Zulip activity, it seems like this has nothing to do with mapped lock guards, or am I missing something?

@tgross35
Copy link
Contributor

This feature adds three structs and we would get three more with the nonpoison module (#134645), plus one more for ReentrantLockGuard (#121440). What if instead we added a perma-unstable LockGuard trait and then replaced these Mapped*Guard types with a single struct Mapped<G: LockGuard> { /* ... */ }? This would save us from having the same user-facing API repeated in seven different locations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants