-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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 RwLock to tokio-sync #1699
add RwLock to tokio-sync #1699
Conversation
366d6bc
to
73fcaa8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for getting this started 👍 I did a quick skim and had a question inline.
@jxs I'm curious — why wrap a Also, as an aside I think we probably want to have a similar design as |
53db2de
to
f3008ff
Compare
Following @carllerche's tip on Discourse to look into Trying to implement the wikipedia algorithm was not trivial due to having to keep the second mutex locked with multiple reads spread, so I looked into other implementations, and the simplest to start off was the one implemented by Qt which also seems the approach followed by Golang: I have updated the code with that implementation |
This is looking really good now! Now we just need to iron out the tests. |
@jxs It'd be better if you avoided force-pushing to this branch now — GitHub isn't great about tracking reviews across force pushes. We can always rebase at the end! |
@asomers Ah, so, I agree completely that we want the deterministic polling tests. I think we also want the racy version as a loom test so that we ensure we actually test that all the interleavings are right. |
Yeah. The loom tests will help to detect races we don't know about, and the deterministic tests will cover races that we already know about. |
update read_write_contested loom test
tests were failing due to new naming of the |
If you look carefully above, you'll see a little box that says:
If you click it, you'll see five unresolved comments from @asomers. If you have actually addressed them, then just mark them as resolved :) |
# Conflicts: # tokio/src/sync/mod.rs # tokio/src/sync/tests/mod.rs
Is there anything left to do here that I could help out with? I see that builds failed but I'm not able to see what failed in them. Are there any outstanding review comments that I could address to help get it moved forward? |
builds are failing due to the loom tests timing out I think, apart from that I think it's ready to be merged cc @carllerche @jonhoo |
Yup, I think this is just missing a final review from @carllerche |
tokio/src/sync/rwlock.rs
Outdated
pub async fn write(&self) -> RwLockWriteGuard<'_, T> { | ||
let _lock = self.w.lock().await; | ||
|
||
let mut permits = vec![]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that this Vec will eventually contain MAX_READS, so it should probably be pre-allocated with that capacity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I merged master into this PR. I will investigate changing semaphore shortly. |
In preparation for the semaphore changes landing, could you add a loom test that checks two concurrent threads attempting to acquire the write lock. This should deadlock. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay 👍 thanks for sticking w/ this!
I notice there are no If I want to |
Motivation
following a conversation on tokio-dev channel to implement a RwLock for tokio, where @carllerche suggested looking at
Watch
and the watchers and watcher_id part, I came up with this solutionSolution
I defined a
RwLock
struct similar to theWatch
struct that wraps aShared
struct, that is composed of an internalstd::sync::RwLock
, and an fnvHashMap
with watchers (id and inner waker).an
AtomicWaker
and an id.Rwlock calls
try_read
andtry_write
onread
andwrite
. iftry_read
ortry_write
return Err::WouldBlock, the current context waker is registered by ref on the innerAtomicWaker
.if
try_read
/try_write
return a Read/Write guard, a new Read/Write struct is returned composed of the inner guard and the list of watchers.When the guard goes out of scope, on it's
Drop
, it iterates the watchers and callswake
on it's innerAtomicWaker
.On
Clone
RwLock adds watcher to the watchers list, and onDrop
removes the current RwLock instance from the watchers list.If there are multiple read and write atempts from the same RwLock instance, their context is registred multiple times to the same waker, i am not so sure of this. I added a couple tests and also imported @asomers
future-locks
onesthanks