mirror of https://github.com/python/cpython
bpo-42972: Fully support GC for _winapi.Overlapped (GH-26381)
This commit is contained in:
parent
3f8d332527
commit
0fa282c55f
|
@ -112,6 +112,20 @@ typedef struct {
|
|||
Py_buffer write_buffer;
|
||||
} OverlappedObject;
|
||||
|
||||
/*
|
||||
Note: tp_clear (overlapped_clear) is not implemented because it
|
||||
requires cancelling the IO operation if it's pending and the cancellation is
|
||||
quite complex and can fail (see: overlapped_dealloc).
|
||||
*/
|
||||
static int
|
||||
overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg)
|
||||
{
|
||||
Py_VISIT(self->read_buffer);
|
||||
Py_VISIT(self->write_buffer.obj);
|
||||
Py_VISIT(Py_TYPE(self));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
overlapped_dealloc(OverlappedObject *self)
|
||||
{
|
||||
|
@ -150,6 +164,7 @@ overlapped_dealloc(OverlappedObject *self)
|
|||
|
||||
CloseHandle(self->overlapped.hEvent);
|
||||
SetLastError(err);
|
||||
PyObject_GC_UnTrack(self);
|
||||
if (self->write_buffer.obj)
|
||||
PyBuffer_Release(&self->write_buffer);
|
||||
Py_CLEAR(self->read_buffer);
|
||||
|
@ -321,6 +336,7 @@ static PyMemberDef overlapped_members[] = {
|
|||
};
|
||||
|
||||
static PyType_Slot winapi_overlapped_type_slots[] = {
|
||||
{Py_tp_traverse, overlapped_traverse},
|
||||
{Py_tp_dealloc, overlapped_dealloc},
|
||||
{Py_tp_doc, "OVERLAPPED structure wrapper"},
|
||||
{Py_tp_methods, overlapped_methods},
|
||||
|
@ -331,7 +347,8 @@ static PyType_Slot winapi_overlapped_type_slots[] = {
|
|||
static PyType_Spec winapi_overlapped_type_spec = {
|
||||
.name = "_winapi.Overlapped",
|
||||
.basicsize = sizeof(OverlappedObject),
|
||||
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
|
||||
Py_TPFLAGS_HAVE_GC),
|
||||
.slots = winapi_overlapped_type_slots,
|
||||
};
|
||||
|
||||
|
@ -339,7 +356,7 @@ static OverlappedObject *
|
|||
new_overlapped(PyObject *module, HANDLE handle)
|
||||
{
|
||||
WinApiState *st = winapi_get_state(module);
|
||||
OverlappedObject *self = PyObject_New(OverlappedObject, st->overlapped_type);
|
||||
OverlappedObject *self = PyObject_GC_New(OverlappedObject, st->overlapped_type);
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
|
@ -351,6 +368,8 @@ new_overlapped(PyObject *module, HANDLE handle)
|
|||
memset(&self->write_buffer, 0, sizeof(Py_buffer));
|
||||
/* Manual reset, initially non-signalled */
|
||||
self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
PyObject_GC_Track(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -2043,12 +2062,37 @@ static PyModuleDef_Slot winapi_slots[] = {
|
|||
{0, NULL}
|
||||
};
|
||||
|
||||
static int
|
||||
winapi_traverse(PyObject *module, visitproc visit, void *arg)
|
||||
{
|
||||
WinApiState *st = winapi_get_state(module);
|
||||
Py_VISIT(st->overlapped_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
winapi_clear(PyObject *module)
|
||||
{
|
||||
WinApiState *st = winapi_get_state(module);
|
||||
Py_CLEAR(st->overlapped_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
winapi_free(void *module)
|
||||
{
|
||||
winapi_clear((PyObject *)module);
|
||||
}
|
||||
|
||||
static struct PyModuleDef winapi_module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
.m_name = "_winapi",
|
||||
.m_size = sizeof(WinApiState),
|
||||
.m_methods = winapi_functions,
|
||||
.m_slots = winapi_slots,
|
||||
.m_traverse = winapi_traverse,
|
||||
.m_clear = winapi_clear,
|
||||
.m_free = winapi_free,
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
|
|
Loading…
Reference in New Issue