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

Add with_upgraded API to upgradable read locks #386

Merged
merged 1 commit into from Jun 5, 2023

Conversation

Jules-Bertholet
Copy link
Contributor

@Jules-Bertholet Jules-Bertholet commented May 26, 2023

RwLockUpgradableReadGuard::upgrade takes the guard by value, so there is currently no way to turn an &mut to an upgradable guard into an &mut to the underlying data.

This PR remedies that with a closure-based API. RwLockUpgradableReadGuard::with_upgraded() takes a mutable reference to an upgradable guard, and:

  1. Upgrades the lock
  2. Retrieves an &mut to the underlying data
  3. Passes the &mut to a user-provided closure
  4. Downgrades the lock back to an upgradable read
  5. Returns the result of the closure.

Allows getting an `&mut` to the data from an `&mut` to the guard.
@Amanieu
Copy link
Owner

Amanieu commented May 27, 2023

This API looks fine, however I'm generally not very happy with upgradable locks and am considering deprecating them: you almost always get better performance by just:

  • taking a read lock to check a condition.
  • if the condition is true, release the read lock, acquire a write lock and re-check the condition.
  • if the condition is still true then perform a modification using the write lock.

Can you explain your use case for upgradable locks and possibly consider moving away from them?

@Jules-Bertholet
Copy link
Contributor Author

My use case: I have a worker thread, that's managing an object/resource. This thread regularly reads from the object, and occasionally writes. In addition, I have a UI thread that is monitoring the object. The UI thread needs to read from the object after every modification (to display the new state), and potentially on a few other occasions as well. No thread, other than the worker, should ever need write access.

My current design, is to shove my object into an Arc<RwLock<Object>>. The worker thread keeps around a &mut ArcRwLockUpgradableReadGuard<Object>, which it can pass around to various functions as needed. When the worker needs to perform a write, it uses with_upgradable. Once the write operation is complete, it uses a channel to notify the UI, which then briefly takes a standard read lock to do what it needs.

@Jules-Bertholet Jules-Bertholet changed the title Add with_upgraded API to upgradeable read locks Add with_upgraded API to upgradable read locks May 28, 2023
@Amanieu Amanieu merged commit 8d64a4a into Amanieu:master Jun 5, 2023
37 checks passed
@Jules-Bertholet Jules-Bertholet deleted the with-upgraded branch June 5, 2023 17:54
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 this pull request may close these issues.

None yet

2 participants