diff -r b9a3d0d515a4 Modules/_winapi.c --- a/Modules/_winapi.c Mon Aug 20 11:38:17 2012 +0200 +++ b/Modules/_winapi.c Mon Aug 20 11:47:16 2012 +0200 @@ -65,18 +65,50 @@ /* Grab CancelIoEx dynamically from kernel32 */ static int has_CancelIoEx = -1; static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED); +typedef struct { + PyObject *OverlappedType; + int has_CancelIoEx; // = -1; +} winapi_state; + + +#define winapi__state(o) ((winapi_state *)PyModule_GetState(o)) + +static int +winapi__clear(PyObject *m) +{ + Py_CLEAR(winapi__state(m)->OverlappedType); + return 0; +} + +static int +winapi__traverse(PyObject *m, visitproc visit, void *arg) +{ + Py_VISIT(winapi__state(m)->OverlappedType); + return 0; +} + +static void +winapi__free(void *m) +{ + winapi__clear((PyObject *)m); +} + +static PyModuleDef winapi_module; + +#define winapi_state_global ((winapi_state *)PyModule_GetState(PyState_FindModule(&winapi_module))) + static int check_CancelIoEx() { - if (has_CancelIoEx == -1) + if (winapi_state_global->has_CancelIoEx == -1) { HINSTANCE hKernel32 = GetModuleHandle("KERNEL32"); * (FARPROC *) &Py_CancelIoEx = GetProcAddress(hKernel32, "CancelIoEx"); - has_CancelIoEx = (Py_CancelIoEx != NULL); + winapi_state_global->has_CancelIoEx = (Py_CancelIoEx != NULL); } - return has_CancelIoEx; + return winapi_state_global->has_CancelIoEx; } @@ -103,6 +135,7 @@ static void overlapped_dealloc(OverlappedObject *self) { + PyTypeObject *type = Py_TYPE(self); DWORD bytes; int err = GetLastError(); if (self->pending) { @@ -121,6 +154,9 @@ if (self->write_buffer.obj) PyBuffer_Release(&self->write_buffer); Py_CLEAR(self->read_buffer); + if((void *)type->tp_dealloc == (void *)overlapped_dealloc) { + Py_DECREF(type); + } PyObject_Del(self); } @@ -214,53 +250,29 @@ {NULL} }; -PyTypeObject OverlappedType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_winapi.Overlapped", - /* tp_basicsize */ sizeof(OverlappedObject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor) overlapped_dealloc, - /* tp_print */ 0, - /* tp_getattr */ 0, - /* tp_setattr */ 0, - /* tp_reserved */ 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 structure wrapper", - /* tp_traverse */ 0, - /* 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 */ 0, - /* 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 */ 0, +static PyType_Slot OverlappedType_slots[] = { + {Py_tp_dealloc, (destructor) overlapped_dealloc}, + {Py_tp_doc, "OVERLAPPED structure wrapper"}, + {Py_tp_methods, overlapped_methods}, + {Py_tp_members, overlapped_members}, + {0, 0} }; +static PyType_Spec OverlappedType_spec = { + "_winapi.Overlapped", + sizeof(OverlappedObject), + 0, + Py_TPFLAGS_DEFAULT, + OverlappedType_slots, +}; + + static OverlappedObject * new_overlapped(HANDLE handle) { OverlappedObject *self; - self = PyObject_New(OverlappedObject, &OverlappedType); + self = PyObject_New(OverlappedObject, (PyTypeObject *)winapi_state_global->OverlappedType); if (!self) return NULL; self->handle = handle; @@ -1249,12 +1261,12 @@ PyModuleDef_HEAD_INIT, "_winapi", NULL, - -1, + sizeof(winapi_state), winapi_functions, NULL, - NULL, - NULL, - NULL + winapi__traverse, + winapi__clear, + winapi__free }; #define WINAPI_CONSTANT(fmt, con) \ @@ -1266,15 +1278,16 @@ PyObject *d; PyObject *m; - if (PyType_Ready(&OverlappedType) < 0) - return NULL; - m = PyModule_Create(&winapi_module); if (m == NULL) return NULL; d = PyModule_GetDict(m); - PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType); + winapi__state(m)->OverlappedType = PyType_FromSpec(&OverlappedType_spec); + if (winapi__state(m)->OverlappedType == NULL) + return NULL; + + PyDict_SetItemString(d, "Overlapped", winapi__state(m)->OverlappedType); /* constants */ WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);