On 1/12/21 7:16 PM, Neil Schemenauer wrote:
On 2021-01-12, Victor Stinner wrote:
It seems like a safer approach is to continue the work on bpo-40077: "Convert static types to PyType_FromSpec()".
I agree that trying to convert static types is a good idea. Another possible bonus might be that we can gain some performance by integrating garbage collection with the Python object memory allocator. Static types frustrate that effort.
Could we have something easier to use than PyType_FromSpec(), for the purposes of coverting existing code? I was thinking of something like:
static PyTypeObject Foo_TypeStatic = { } static PyTypeObject *Foo_Type;
PyInit_foo(void) { Foo_Type = PyType_FromStatic(&Foo_TypeStatic); }
The PyType_FromStatic() would return a new heap type, created by copying the static type. The static type could be marked as being unusable (e.g. with a type flag).
Unfortunately, it's not just the creation that needs to be changed. You also need to decref Foo_Type somewhere. Your example is for "single-phase init" modules (pre-PEP 489). Those don't have a dealloc hook, so they will leak memory (e.g. in multiple Py_Initialize/Py_Finalize cycles). Multi-phase init (PEP 489) allows multiple module instances of extension modules. Assigning PyType_FromStatic's result to a static pointer would mean that every instance of the module will create a new type, and overwrite any existing one. And the deallocation will either leave a dangling pointer or NULL the pointer for other module instances. So, you need to make the type part of the module state, so that the module has proper ownership of the type. And that means you need to access the type from the module state any time you need to use it. At that point, IMO, PyType_FromStatic saves you so little work that it's not worth supporting a third variation of type creation code.