-
Notifications
You must be signed in to change notification settings - Fork 760
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 Clone for PyObject / Py<T> #908
Conversation
Wow. Awesome 👍
The logic seems correct to me, though we need to test it carefully. |
That sounds excellent! I would love to remove a bunch of those straightforward implementations from my code base. |
869d5df
to
f28176d
Compare
Pushed some tests - ready for review! |
@@ -501,32 +544,23 @@ mod test { | |||
|
|||
#[test] | |||
fn test_allow_threads() { |
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 had to simplify this test because otherwise it could have race conditions with test_clone_in_allow_threads
, as both of them are testing the same global state.
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.
EDIT: I had to remove test_clone_in_allow_threads
anyway, because it was very brittle checking the global state with potentially many other tests all changing the state. But I still think the simplification I did here makes sense.
a40225e
to
cd889e8
Compare
cd889e8
to
86af474
Compare
// Since we have a valid PyString and replace any surrogates, assume success. | ||
debug_assert!(!py_bytes.is_null()); | ||
// ensure DECREF will be called | ||
gil::register_pointer(NonNull::new(py_bytes).unwrap()); |
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.
Usage of register_pointer
was broken since my change to pointer drop immediately with GIL, suprised this test wasn't failing (probably luck).
I have rewritten this to use usual owned references.
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.
👍
// Since we have a valid PyString and replace any surrogates, assume success. | ||
debug_assert!(!py_bytes.is_null()); | ||
// ensure DECREF will be called | ||
gil::register_pointer(NonNull::new(py_bytes).unwrap()); |
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.
👍
Thank you! |
I had this idea suddenly that similar to how we store pending
Py_DECREF
, I believe we can also store pendingPy_INCREF
, as long as all increfs are done before decrefs.This allows
Py
andPyObject
to haveClone
implemented. If the GIL is held the reference count is updated immediately, otherwise the reference count increase is saved for the next time a thread acquires the GIL.I have been mulling this over in my head and cannot find a way that this produces a dangling
PyObject
. Please do challenge me on this one though - I would prefer to be proved wrong and we don't merge this if it is not safe.I will add tests later - gotta go to work! Just wanted to share it with you first as I think having
Clone
for these types will open the way for simplifying some things. (e.g. I think we could potentially add blanket implToPyObject
for allT: Clone
? Haven't thought too hard about that.)