-
Notifications
You must be signed in to change notification settings - Fork 740
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
Make PyClassBorrowChecker thread safe #4544
base: main
Are you sure you want to change the base?
Conversation
Hmm, not sure I follow why taking an |
I realized today that if I make |
BorrowFlag::UNUSED, | ||
BorrowFlag::HAS_MUTABLE_BORROW, | ||
Ordering::SeqCst, | ||
Ordering::SeqCst, |
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 conservatively chose SeqCst
for the ordering of all operations, I'm not sure if a different ordering is OK.
CodSpeed Performance ReportMerging #4544 will not alter performanceComparing Summary
|
ab32156
to
fb19488
Compare
Ping @colesbury - I'd appreciate a code review from you if you have some spare cycles. |
src/pycell/impl_.rs
Outdated
Err(..) => { | ||
// value changed under us, need to reload and try again | ||
let value = self.0.load(Ordering::Relaxed); |
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.
Do we need to reload? Isn't the value in Err(..)
what we want?
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.
Oh, either way: the let
here causes value
to be rebound, which means that teh compare_exchange is always comparing to the original value, which I don't think is what you want.
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! much clearer this way without the second load.
pytests/src/pyclasses.rs
Outdated
|
||
fn __next__(&mut self) -> usize { | ||
let should_wait = self.count == 0; | ||
self.count += 1; |
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.
reminder to myself this should use rust atomics
I feel quite strongly that we shouldn't merge this PR. The semantics in #4265 (comment) make much more sense to me. |
@mejrs I'm very much in agreement with you that keeping these "refcell-like" semantics on the freethreaded build is likely to be completely unusable in real-world conditions. Would you be prepared to accept this PR merging in 0.23 with the understanding that we will follow up in 0.24 with something akin to #4265 (comment), i.e. a more realistic design. I think this allows us to make PyO3 sound for downstream testing of free-threading without needing to introduce breaking changes (of which there are already enough collected for this release). |
I disagree strongly that these are unusable in real-world situations. I did a review of pyca/cryptography and these semantics would be appropriate for all of our usage of non-frozen pyclasses. The reason is that while these types require mutable access, there's no particularly coherent behavior for concurrent multi-threaded usage. These types are, for example, iterators and hashers. There's no real world usage for concurrent mutable use. |
I'm OK with that.
They may work in your situation, but not in general. Imagine a List-like pyclass with a |
Ref #4265 (comment) and replies from @alex.
I tried doing this with an
AtomicUsize
but becausetry_borrow
accepts an immutable reference, I couldn't figure out a way to get that to work without keeping theCell
. A mutex seemed like a more natural choice for the existing code structure.I think in principle we could use a mutex on the GIL-enabled build as well, since the lock is only held very briefly in rust to update the borrow checker state.
Is the new test that only triggers on the free-threaded build OK? I could also write it to test that there isn't an exception on the GIL-enabled build.