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 Mutex::unlock() #81872

Closed
1 of 3 tasks
mark-i-m opened this issue Feb 8, 2021 · 21 comments · Fixed by #121736
Closed
1 of 3 tasks

Tracking Issue for Mutex::unlock() #81872

mark-i-m opened this issue Feb 8, 2021 · 21 comments · Fixed by #121736
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC disposition-close This PR / issue is in PFCP or FCP with a disposition to close it. finished-final-comment-period The final comment period is finished for this PR / Issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@mark-i-m
Copy link
Member

mark-i-m commented Feb 8, 2021

Feature gate: #![feature(mutex_unlock)]

This is a tracking issue for the Mutex::unlock function. The goal of this function is to replace drop(mutex_guard) which doesn't clear express that a synchronization event is occurring.

Some earlier discussion, including a previous implementation: #79434 (comment)

Public API

// std::sync::Mutex

impl<T> Mutex<T> {
    /// Immediately drops the guard, unlocking the mutex.
    ///
    /// This is equivalent to `drop(guard)`, but it is more self-documenting.
    pub fn unlock(guard: MutexGuard<T>) {
        drop(guard);
    }
}

Steps / History

Unresolved Questions

  • Should an analogous function be added to RwLock? It would be a bit more complicated.
@mark-i-m mark-i-m 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 Feb 8, 2021
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Feb 19, 2021
@mbrubeck
Copy link
Contributor

mbrubeck commented Jul 1, 2021

I don't think this needs to require T: Sized. Should it be moved to impl<T: ?Sized> Mutex<T>?

@mark-i-m
Copy link
Member Author

mark-i-m commented Jul 1, 2021

I can make a PR for that...

JohnTitor added a commit to JohnTitor/rust that referenced this issue Jul 1, 2021
JohnTitor added a commit to JohnTitor/rust that referenced this issue Jul 1, 2021
@ibraheemdev
Copy link
Member

A bit pedantic, but wouldn't it make sense for the drop impl for MutexGuard to call unlock, and the logic to be moved there?

@mbrubeck
Copy link
Contributor

A bit pedantic, but wouldn't it make sense for the drop impl for MutexGuard to call unlock, and the logic to be moved there?

MutexGuard::drop takes &mut self, so it can't easily call unlock, which consumes the MutexGuard by value.

@ibraheemdev
Copy link
Member

Ah right, that is problematic.

@frogtd
Copy link
Contributor

frogtd commented Aug 21, 2021

The drop function call is useless BTW, but it could make it slightly more clear.

@StrongerXi
Copy link

Any progress on this? Wondering why it's still pending...

@mark-i-m
Copy link
Member Author

Mainly, I think this is lacking manpower to drive it forward...

@jw2476
Copy link

jw2476 commented Sep 1, 2022

What needs to be done to get this into stable?

@BurntSushi
Copy link
Member

My own inclination is to not accept this. It seems likely to cause folks to use this when it would just be better to let drop handle it. It's idiomatic for drop to deal with these sorts of things IMO, and I'm not convinced that the self-documenting nature of this method is enough to motivate setting a precedent for this.

Curious to hear what the rest of the team thinks.

@rfcbot fcp close

@rfcbot
Copy link

rfcbot commented Feb 22, 2023

Team member @BurntSushi has proposed to close this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-close This PR / issue is in PFCP or FCP with a disposition to close it. labels Feb 22, 2023
@mark-i-m
Copy link
Member Author

@BurntSushi Reading back on the thread, I realize the motivation is not really discussed.

I have a very particular use cases in mind. I agree that normally, it should be idiomatic to just let the lock drop by going out of scope. However, there are cases when this is not preferable, and currently one must call drop(guard) to get the desired behavior, which is a non-obvious way to indicate a lock being released.

  1. Avoiding deadlocks. Example:

    let locked1 = my_btree.lock().unwrap();
    // do a bunch of stuff with locked1
    
    let locked2 = my_other_btree.lock().unwrap();
    // do a bunch of stuff with locked2 
    
    wait_for_other_thread();
    // OOPS! Deadlock! Other thread needs to acquire the locks.
  2. Performance

    let locked1 = my_btree.lock().unwrap();
    // do stuff with my_btree
    
    compute_something_expensive();
    
    // OOPS! All other threads blocked while we compute something expensive!
  3. Documentation -- in long functions, the only way I know of to create a short critical section is the use a new { } block or use drop(guard), neither of which seems great... they're hard to see/search for; the { } approach causes rightward drift, etc.

    fn really_long_fn() {
       // do a bunch of stuff      
    
       {
         let locked = my_data.lock().unwrap();
         // do stuff
       } // unlock
    
       // more stuff
    
      {
         // Another critical section
       } 
    
       // more stuff
    
       // Another critical section (alternately using braces)
       let locked = my_data.lock().unwrap();
       // do stuff
       drop(locked);
    }

Anyway, I hope that's useful.

@BurntSushi
Copy link
Member

Yeah that all makes sense. I'm just not sure it's worth adding an explicit unlock for those use cases instead of focusing effort on drop(locked). It's less direct, but drop is a critical part of how Rust works and it's important for folks to grapple with it. There's similar ideas in place with things like File and other guards, like those for RefCell.

@mark-i-m
Copy link
Member Author

It's less direct, but drop is a critical part of how Rust works and it's important for folks to grapple with it. There's similar ideas in place with things like File and other guards, like those for RefCell.

@BurntSushi Do those cases have performance or correctness implications? I guess RefCell could have an analogous problem to deadlocks. I guess I'm arguing that locks are significantly more common to have to manually drop than the others and that the impact is significantly more difficult to debug, as to make it deserve some special treatment. (That might be entirely because of the types of projects I work on, though).

instead of focusing effort on drop(locked)

I'm intrigued. What kind of efforts are you thinking of? How do you see manual drop being improved? I'm open to other solutions.

@dtolnay
Copy link
Member

dtolnay commented Feb 22, 2023

FWIW I like this method. I implemented Mutex::unlock, with the same signature, for crosvm's Mutex in Chrome OS more than a year before the same method was proposed for the standard library: https://chromium.googlesource.com/chromiumos/platform/crosvm/+/b70614d2526a562ac7a6eae4b734198908aafdec%5E%21. But I also sympathize with the point that it will inevitably get used in situations it definitely shouldn't be. Normally I am the one making that argument, such as for #80437.

@tgross35
Copy link
Contributor

Relevant zulip thread https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/stabilizing.20Mutex.3A.3Aunlock.28.29

It was brought up there that maybe some closure-based API (some_mutex.with_lock(|g| ... )) would be a good way to express guard scope when the default drop time isn't ideal or isn't clear. I believe that is the case this PR seeks to address.

I have to agree with that sentiment, especially since many times you only need to run one or two statements while a mutex is locked. Encouraging use of a closure to perform small-scoped operations seems like very idiomatic Rust. Having a wrapper around an existing public API that doesn't add new functionality - less so.

@mark-i-m
Copy link
Member Author

@tgross35 I do think that a closure-based interface like that can be useful, but it also has some big limitations:

  • it increases rightward drift, especially if you have multiple locks.
  • creating the closure often requires moving or borrowing other variables in the environment, which might be painful or inefficient (e.g. if they are not Copy or Clone types).
  • closures mess with ?, break, continue, and other control-flow constructs.

@tgross35
Copy link
Contributor

Yeah, there are of course problems and I see it was discussed in #81873. My point was moreso just that I don't think it would make sense to have both this and a (RFC reviewed) closure method, since they kind of target similar use cases. And for the remaining 15% of cases, drop or { scope } would work fine. But I'm a spectator and that's just mho.

For what it's worth on rightward drift with >1 mutex, I think most cases could get by sharing the scope of the first mutex.

mtx1.with_lock(|guard1| {
    let guard2 = mtx2.lock().unwrap();
    let guard3 = mtx3.lock().unwrap();
}); // lock it all back up

@m-ou-se m-ou-se added the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Feb 28, 2023
@Amanieu
Copy link
Member

Amanieu commented Feb 28, 2023

See #61976 for a previous attempt to add Mutex::with.

@rfcbot rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels Mar 7, 2023
@rfcbot
Copy link

rfcbot commented Mar 7, 2023

🔔 This is now entering its final comment period, as per the review above. 🔔

@m-ou-se m-ou-se removed the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Mar 14, 2023
@rfcbot rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Mar 17, 2023
@rfcbot
Copy link

rfcbot commented Mar 17, 2023

The final comment period, with a disposition to close, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

@apiraino apiraino removed the to-announce Announce this issue on triage meeting label Mar 23, 2023
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Mar 24, 2023
Add block-based mutex unlocking example

This modifies the existing example in the Mutex docs to show both `drop()` and block based early unlocking.

Alternative to rust-lang#81872, which is getting closed.
workingjubilee added a commit to workingjubilee/rustc that referenced this issue Mar 1, 2024
…-mutex-unlock, r=jhpratt

Remove `Mutex::unlock` Function

As of the completion of the FCP in rust-lang#81872 (comment), it has come to the conclusion to be closed.

This PR removes the function entirely in light of the above.

Closes rust-lang#81872.
workingjubilee added a commit to workingjubilee/rustc that referenced this issue Mar 1, 2024
…-mutex-unlock, r=jhpratt

Remove `Mutex::unlock` Function

As of the completion of the FCP in rust-lang#81872 (comment), it has come to the conclusion to be closed.

This PR removes the function entirely in light of the above.

Closes rust-lang#81872.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Mar 1, 2024
…-mutex-unlock, r=jhpratt

Remove `Mutex::unlock` Function

As of the completion of the FCP in rust-lang#81872 (comment), it has come to the conclusion to be closed.

This PR removes the function entirely in light of the above.

Closes rust-lang#81872.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Mar 1, 2024
…-mutex-unlock, r=jhpratt

Remove `Mutex::unlock` Function

As of the completion of the FCP in rust-lang#81872 (comment), it has come to the conclusion to be closed.

This PR removes the function entirely in light of the above.

Closes rust-lang#81872.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Mar 1, 2024
…-mutex-unlock, r=jhpratt

Remove `Mutex::unlock` Function

As of the completion of the FCP in rust-lang#81872 (comment), it has come to the conclusion to be closed.

This PR removes the function entirely in light of the above.

Closes rust-lang#81872.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Mar 1, 2024
…-mutex-unlock, r=jhpratt

Remove `Mutex::unlock` Function

As of the completion of the FCP in rust-lang#81872 (comment), it has come to the conclusion to be closed.

This PR removes the function entirely in light of the above.

Closes rust-lang#81872.
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Mar 1, 2024
Rollup merge of rust-lang#121736 - HTGAzureX1212:HTGAzureX1212/remove-mutex-unlock, r=jhpratt

Remove `Mutex::unlock` Function

As of the completion of the FCP in rust-lang#81872 (comment), it has come to the conclusion to be closed.

This PR removes the function entirely in light of the above.

Closes rust-lang#81872.
doutv added a commit to okx/plonky2 that referenced this issue Jun 3, 2024
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 disposition-close This PR / issue is in PFCP or FCP with a disposition to close it. finished-final-comment-period The final comment period is finished for this PR / Issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.