diff --git a/Misc/NEWS.d/next/C API/2020-11-22-13-46-06.bpo-1635741.-fJLzA.rst b/Misc/NEWS.d/next/C API/2020-11-22-13-46-06.bpo-1635741.-fJLzA.rst new file mode 100644 index 00000000000000..da1e4cb9ef17e3 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-11-22-13-46-06.bpo-1635741.-fJLzA.rst @@ -0,0 +1 @@ +Port :mod:`resource` extension module to module state diff --git a/Modules/resource.c b/Modules/resource.c index 4f5dcf84387888..f10a80f4776863 100644 --- a/Modules/resource.c +++ b/Modules/resource.c @@ -63,8 +63,20 @@ static PyStructSequence_Desc struct_rusage_desc = { 16 /* n_in_sequence */ }; -static int initialized; -static PyTypeObject StructRUsageType; +typedef struct { + PyTypeObject *StructRUsageType; +} resourcemodulestate; + + +static inline resourcemodulestate* +get_resource_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (resourcemodulestate *)state; +} + +static struct PyModuleDef resourcemodule; /*[clinic input] resource.getrusage @@ -91,7 +103,8 @@ resource_getrusage_impl(PyObject *module, int who) return NULL; } - result = PyStructSequence_New(&StructRUsageType); + result = PyStructSequence_New( + get_resource_state(module)->StructRUsageType); if (!result) return NULL; @@ -336,10 +349,10 @@ resource_methods[] = { /* Module initialization */ - static int resource_exec(PyObject *module) { + resourcemodulestate *state = get_resource_state(module); #define ADD_INT(module, value) \ do { \ if (PyModule_AddIntConstant(module, #value, value) < 0) { \ @@ -353,13 +366,12 @@ resource_exec(PyObject *module) Py_DECREF(PyExc_OSError); return -1; } - if (!initialized) { - if (PyStructSequence_InitType2(&StructRUsageType, - &struct_rusage_desc) < 0) - return -1; - } - if(PyModule_AddType(module, &StructRUsageType) < 0) { + state->StructRUsageType = PyStructSequence_NewType(&struct_rusage_desc); + if (state->StructRUsageType == NULL) { + return -1; + } + if (PyModule_AddType(module, state->StructRUsageType) < 0) { return -1; } @@ -483,8 +495,6 @@ resource_exec(PyObject *module) Py_DECREF(v); return -1; } - - initialized = 1; return 0; #undef ADD_INT @@ -495,12 +505,32 @@ static struct PyModuleDef_Slot resource_slots[] = { {0, NULL} }; +static int +resourcemodule_traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(get_resource_state(m)->StructRUsageType); + return 0; +} + +static int +resourcemodule_clear(PyObject *m) { + Py_CLEAR(get_resource_state(m)->StructRUsageType); + return 0; +} + +static void +resourcemodule_free(void *m) { + resourcemodule_clear((PyObject *)m); +} + static struct PyModuleDef resourcemodule = { PyModuleDef_HEAD_INIT, .m_name = "resource", - .m_size = 0, + .m_size = sizeof(resourcemodulestate), .m_methods = resource_methods, .m_slots = resource_slots, + .m_traverse = resourcemodule_traverse, + .m_clear = resourcemodule_clear, + .m_free = resourcemodule_free, }; PyMODINIT_FUNC