-
Notifications
You must be signed in to change notification settings - Fork 23
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
Refcounting Smart Pointers #702
base: master
Are you sure you want to change the base?
Refcounting Smart Pointers #702
Conversation
6fd66d6
to
6b59d1e
Compare
1aef130
to
5eee799
Compare
In particular, there are 4 possible sets of smart pointer semantics defined here corresponding to the cases where a PyObject pointer does or does not own a reference and where a pointer is or is not allowed to be null valued.
The order of the conditions in enable_if_t matters since, in some cases, the compiler uses short circuit evaluation of the compile-time constant expressions to simplify the enable_if condition so that it no longer depends on the inputs and only depends on the template parameters of the class being constructed, which, then, causes an error since that isn't allowed.
First, Rewrite non-null pointer types to use asserts rather than an absolute assumption that the pointer type is not null. Second, add move assignment operators to avoid unneeded incref/decrefs when assigning between these smart pointer classes. Third, allow implicit conversions to happen between all four of these classes. Conversions from pointers that may be null to pointers that count null as an uninitialized state now raise an exception if a null value is encountered, and all other constructors are marked as noexcept. Fourth, add a method to release an owned reference from a given pointer. This replaces the old release method and eliminates various segfaults that were due to over-agressive calls to decref.
Rename the existing RAII class for acquiring the GIL to something slightly less verbose.
reference to a reference that is known not to be null.
are always valid.
depending on the type of reference the smart pointer wraps.
…takes an rvalue reference so that its inputs are explicitly invalidated when release is used.
Fix some erroneous noexcept statements. Also add some more helpful assert statements.
5eee799
to
9e8bf42
Compare
I think this is good to go now. The test failures are not related to this PR. Here are my future plans with this (in no particular order):
|
One high level question - is there a description of how they work and why they're designed the way they are, so that people using them can refer to that to develop their mental model of correct vs incorrect code? Would be good to link to that description from the README/getting started. |
Thus far I've just been doing that via thorough commenting. I can put together a design doc if you'd like though. |
That would be awesome, yeah, When I first used the python C API, I found https://docs.python.org/2/c-api/intro.html#reference-counts very useful to orient myself about reference counts, you might call out specific things from there and describe how the types you've created make it easier to produce correct code. |
Sure, that sounds like a great idea. I'll add that in here as well. Thanks! |
So, as this is, things still segfault, and there's a compilation error with MSVC that I need to track down. I'll put this up here anyway so we can discuss the proposed API while I track down the remaining errors. I also still need to add an assignment operator that allows moving from an rvalue reference.
Ultimately, I'd like to see a class like this used to interface between our binding code that's written in C++ and Cython. It'd be ideal if we could also use classes like this to interact with many of the built in Python C API functions. The goal there would be to make it so that compile-time errors can be thrown when a function is used with incorrect reference semantics or null handling. Encoding thse semantics into the type system seems like a good way to do that.