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

Port the _overlapped extension module to multi-phase initialization (PEP 489).
This commit is contained in:
Mohamed Koubaa 2020-09-07 08:12:40 -05:00 committed by GitHub
parent 426f2b4f13
commit 2aabc3200b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 69 deletions

View File

@ -0,0 +1,2 @@
Port the :mod:`_overlapped` extension module to multi-phase initialization
(:pep:`489`).

View File

@ -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;
}
static int
overlapped_clear(PyObject *module)
{
OverlappedState *state = overlapped_get_state(module);
Py_CLEAR(state->overlapped_type);
return 0;
}
static void
overlapped_free(void *module)
{
overlapped_clear((PyObject *)module);
}
#define WINAPI_CONSTANT(fmt, con) \
PyDict_SetItemString(d, #con, Py_BuildValue(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)
PyMODINIT_FUNC
PyInit__overlapped(void)
static int
overlapped_exec(PyObject *module)
{
PyObject *m, *d;
/* Ensure WSAStartup() called before initializing function pointers */
m = PyImport_ImportModule("_socket");
if (!m)
return NULL;
Py_DECREF(m);
if (initialize_function_pointers() < 0)
return NULL;
m = PyModule_Create(&overlapped_module);
if (PyModule_AddType(m, &OverlappedType) < 0) {
return NULL;
PyObject *socket_module = PyImport_ImportModule("_socket");
if (!socket_module) {
return -1;
}
d = PyModule_GetDict(m);
Py_DECREF(socket_module);
if (initialize_function_pointers() < 0) {
return -1;
}
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);
}