[Python-checkins] bpo-1635741: Port _overlapped module to multi-phase init (GH-22051)

Mohamed Koubaa webhook-mailer at python.org
Mon Sep 7 09:12:45 EDT 2020


https://github.com/python/cpython/commit/2aabc3200bf03d2ec1aa987e1e20db704948111e
commit: 2aabc3200bf03d2ec1aa987e1e20db704948111e
branch: master
author: Mohamed Koubaa <koubaa.m at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-09-07T15:12:40+02:00
summary:

bpo-1635741: Port _overlapped module to multi-phase init (GH-22051)

Port the _overlapped extension module to multi-phase initialization (PEP 489).

files:
A Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst
M Modules/overlapped.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst b/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst
new file mode 100644
index 0000000000000..76f985bb87b4e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-22-35.bpo-1635741.CnRME3.rst	
@@ -0,0 +1,2 @@
+Port the :mod:`_overlapped` extension module to multi-phase initialization
+(:pep:`489`).
diff --git a/Modules/overlapped.c b/Modules/overlapped.c
index 5e7a1bbba7678..3829932070a96 100644
--- a/Modules/overlapped.c
+++ b/Modules/overlapped.c
@@ -100,6 +100,19 @@ typedef struct {
     };
 } OverlappedObject;
 
+typedef struct {
+    PyTypeObject *overlapped_type;
+} OverlappedState;
+
+static inline OverlappedState*
+overlapped_get_state(PyObject *module)
+{
+    void *state = PyModule_GetState(module);
+    assert(state != NULL);
+    return (OverlappedState *)state;
+}
+
+
 /*
  * Map Windows error codes to subclasses of OSError
  */
@@ -706,8 +719,11 @@ Overlapped_dealloc(OverlappedObject *self)
     }
 
     Overlapped_clear(self);
-    PyObject_Del(self);
     SetLastError(olderr);
+
+    PyTypeObject *tp = Py_TYPE(self);
+    PyObject_Del(self);
+    Py_DECREF(tp);
 }
 
 
@@ -1846,45 +1862,22 @@ static PyGetSetDef Overlapped_getsets[] = {
     {NULL},
 };
 
-PyTypeObject OverlappedType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    /* tp_name           */ "_overlapped.Overlapped",
-    /* tp_basicsize      */ sizeof(OverlappedObject),
-    /* tp_itemsize       */ 0,
-    /* tp_dealloc        */ (destructor) Overlapped_dealloc,
-    /* tp_vectorcall_offset */ 0,
-    /* tp_getattr        */ 0,
-    /* tp_setattr        */ 0,
-    /* tp_as_async       */ 0,
-    /* tp_repr           */ 0,
-    /* tp_as_number      */ 0,
-    /* tp_as_sequence    */ 0,
-    /* tp_as_mapping     */ 0,
-    /* tp_hash           */ 0,
-    /* tp_call           */ 0,
-    /* tp_str            */ 0,
-    /* tp_getattro       */ 0,
-    /* tp_setattro       */ 0,
-    /* tp_as_buffer      */ 0,
-    /* tp_flags          */ Py_TPFLAGS_DEFAULT,
-    /* tp_doc            */ _overlapped_Overlapped__doc__,
-    /* tp_traverse       */ (traverseproc)Overlapped_traverse,
-    /* tp_clear          */ 0,
-    /* tp_richcompare    */ 0,
-    /* tp_weaklistoffset */ 0,
-    /* tp_iter           */ 0,
-    /* tp_iternext       */ 0,
-    /* tp_methods        */ Overlapped_methods,
-    /* tp_members        */ Overlapped_members,
-    /* tp_getset         */ Overlapped_getsets,
-    /* tp_base           */ 0,
-    /* tp_dict           */ 0,
-    /* tp_descr_get      */ 0,
-    /* tp_descr_set      */ 0,
-    /* tp_dictoffset     */ 0,
-    /* tp_init           */ 0,
-    /* tp_alloc          */ 0,
-    /* tp_new            */ _overlapped_Overlapped,
+static PyType_Slot overlapped_type_slots[] = {
+    {Py_tp_dealloc, Overlapped_dealloc},
+    {Py_tp_doc, (char *)_overlapped_Overlapped__doc__},
+    {Py_tp_traverse, Overlapped_traverse},
+    {Py_tp_methods, Overlapped_methods},
+    {Py_tp_members, Overlapped_members},
+    {Py_tp_getset, Overlapped_getsets},
+    {Py_tp_new, _overlapped_Overlapped},
+    {0,0}
+};
+
+static PyType_Spec overlapped_type_spec = {
+    .name = "_overlapped.Overlapped",
+    .basicsize = sizeof(OverlappedObject),
+    .flags = Py_TPFLAGS_DEFAULT,
+    .slots = overlapped_type_slots
 };
 
 static PyMethodDef overlapped_functions[] = {
@@ -1904,41 +1897,65 @@ static PyMethodDef overlapped_functions[] = {
     {NULL}
 };
 
-static struct PyModuleDef overlapped_module = {
-    PyModuleDef_HEAD_INIT,
-    "_overlapped",
-    NULL,
-    -1,
-    overlapped_functions,
-    NULL,
-    NULL,
-    NULL,
-    NULL
-};
+static int
+overlapped_traverse(PyObject *module, visitproc visit, void *arg)
+{
+    OverlappedState *state = overlapped_get_state(module);
+    Py_VISIT(state->overlapped_type);
+    return 0;
+}
 
-#define WINAPI_CONSTANT(fmt, con) \
-    PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
+static int
+overlapped_clear(PyObject *module)
+{
+    OverlappedState *state = overlapped_get_state(module);
+    Py_CLEAR(state->overlapped_type);
+    return 0;
+}
 
-PyMODINIT_FUNC
-PyInit__overlapped(void)
+static void
+overlapped_free(void *module)
 {
-    PyObject *m, *d;
+    overlapped_clear((PyObject *)module);
+}
 
+#define WINAPI_CONSTANT(fmt, con) \
+    do { \
+        PyObject *value = Py_BuildValue(fmt, con); \
+        if (value == NULL) { \
+            return -1; \
+        } \
+        if (PyModule_AddObject(module, #con, value) < 0 ) { \
+            Py_DECREF(value); \
+            return -1; \
+        } \
+    } while (0)
+
+static int
+overlapped_exec(PyObject *module)
+{
     /* Ensure WSAStartup() called before initializing function pointers */
-    m = PyImport_ImportModule("_socket");
-    if (!m)
-        return NULL;
-    Py_DECREF(m);
+    PyObject *socket_module = PyImport_ImportModule("_socket");
+    if (!socket_module) {
+        return -1;
+    }
 
-    if (initialize_function_pointers() < 0)
-        return NULL;
+    Py_DECREF(socket_module);
 
-    m = PyModule_Create(&overlapped_module);
-    if (PyModule_AddType(m, &OverlappedType) < 0) {
-        return NULL;
+    if (initialize_function_pointers() < 0) {
+        return -1;
     }
 
-    d = PyModule_GetDict(m);
+    OverlappedState *st = overlapped_get_state(module);
+    st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(
+        module, &overlapped_type_spec, NULL);
+    if (st->overlapped_type == NULL) {
+        return -1;
+    }
+
+    if (PyModule_AddType(module, st->overlapped_type) < 0) {
+        return -1;
+    }
 
     WINAPI_CONSTANT(F_DWORD,  ERROR_IO_PENDING);
     WINAPI_CONSTANT(F_DWORD,  ERROR_NETNAME_DELETED);
@@ -1952,5 +1969,27 @@ PyInit__overlapped(void)
     WINAPI_CONSTANT(F_DWORD,  SO_UPDATE_CONNECT_CONTEXT);
     WINAPI_CONSTANT(F_DWORD,  TF_REUSE_SOCKET);
 
-    return m;
+    return 0;
+}
+
+static PyModuleDef_Slot overlapped_slots[] = {
+    {Py_mod_exec, overlapped_exec},
+    {0, NULL}
+};
+
+static struct PyModuleDef overlapped_module = {
+    PyModuleDef_HEAD_INIT,
+    .m_name = "_overlapped",
+    .m_size = sizeof(OverlappedState),
+    .m_methods = overlapped_functions,
+    .m_slots = overlapped_slots,
+    .m_traverse = overlapped_traverse,
+    .m_clear = overlapped_clear,
+    .m_free = overlapped_free
+};
+
+PyMODINIT_FUNC
+PyInit__overlapped(void)
+{
+    return PyModuleDef_Init(&overlapped_module);
 }



More information about the Python-checkins mailing list