Add thread-safe cache initialization section to free-threading docs#7582
Add thread-safe cache initialization section to free-threading docs#7582da-woods merged 7 commits intocython:masterfrom
Conversation
4e18108 to
1e72fe6
Compare
docs/src/userguide/freethreading.rst
Outdated
| def __get__(B self): | ||
| def closure(): | ||
| self._py_obj = A(create_c_object(self.key)) | ||
| self.cache_flag.store(True) |
There was a problem hiding this comment.
This I think belongs to your later example
docs/src/userguide/freethreading.rst
Outdated
| self.key = key | ||
| self._py_obj = None | ||
|
|
||
| property obj: |
There was a problem hiding this comment.
I'd probably recommend just using the Python syntax:
@property
def obj(self):
...
It should end up as exactly the same code, and we general try to steer people to Python-type syntax where available.
|
One more comment (which is maybe more a suggestion to "how to do it in SciPy" than this documentation PR): you could avoid the closure by using the "args" version of I'll have a proper look at the proposed documentation tomorrow |
|
The C++ compiler complains: |
docs/src/userguide/freethreading.rst
Outdated
| return self._py_obj | ||
|
|
||
| If you want to avoid the need to define a closure or wrapper object in every | ||
| call to ``__get__``, you can also use an atomic boolean flag to indicate whether |
There was a problem hiding this comment.
should be obj now
So I think that's because you're casting the function to |
|
Fixup to make my proposed example work is in #7585 (together with a small amount of working code that demonstrates it) |
Yes, that's wrong. Sorry for the confusion, I was at the end of a long day... I can confirm that with your Cython branch I'm able to get rid of the closure in SciPy. Are you planning to backport that for 3.2.5? And if so, when were you planning to cut a new bugfix release? |
|
It probably makes sense to discuss |
Yeah agree with all of this. I suspect it probably also isn't work having the I've been trying to think of a way of making passing Python arguments in a bit nicer, but unfortunately I'm not coming up with many good ideas (especially trying to keep it as a library feature rather than adding anything to the language). |
da-woods
left a comment
There was a problem hiding this comment.
There's a few bits where I think the code won't quite compile correctly. We've typically put our documentation examples as separate files in the docs/examples directory, and then they at least get compiled (although not run) to verify correctness.
I wonder if the example could be cut down further partly for the sake of simplicity and partly to get it to something compilable without too many extra details.
How about omitting class A and just saying
from somewhere import expensive_python_function
cdef void init_py_obj(void *void_instance):
cdef B instance = <B>void_instance
instance._py_obj = expensive_python_function(instance.key)
and then the details of what you're initializing _py_obj with disappear completely.
docs/src/userguide/freethreading.rst
Outdated
| def __init__(A self, c_object *obj): | ||
| self.obj = c_object |
There was a problem hiding this comment.
I don't think this'll work because you can't pass C pointers to def functions
docs/src/userguide/freethreading.rst
Outdated
|
|
||
| cdef class B: | ||
| cdef: | ||
| int key |
There was a problem hiding this comment.
I think we're missing the declaration for _py_obj here
docs/src/userguide/freethreading.rst
Outdated
| example casts to ``void *`` to work around that. This is safe so long as the | ||
| ``cdef`` initialization function doesn't need any data managed by Python objects. |
There was a problem hiding this comment.
I'm not quite sure about the "This is safe..." section.
From my point of view it's safe because we hold an actual reference to self for the entire duration of the call_once call
There was a problem hiding this comment.
I adopted a slight tweak of this language, thanks!
docs/src/userguide/freethreading.rst
Outdated
| from libcpp.mutex cimport py_safe_call_object_once, py_safe_once_flag | ||
|
|
There was a problem hiding this comment.
Indentation looks wrong here
|
Thanks for the pointer about the examples directory. I moved the code examples to there. I also decided to delete one of the |
Co-authored-by: da-woods <dw-git@d-woods.co.uk>
|
OK, I think tests are passing again. Anything else needed here? |
Based on my experience working on scipy/scipy#24799.