diff -r bee68447ea63 Modules/selectmodule.c --- a/Modules/selectmodule.c Thu Aug 16 22:04:36 2012 +0200 +++ b/Modules/selectmodule.c Thu Aug 16 22:59:31 2012 +0200 @@ -62,6 +62,70 @@ # endif #endif +typedef struct { + PyObject *poll_Type; +#ifdef HAVE_SYS_DEVPOLL_H + PyObject *devpoll_Type; +#endif +#ifdef HAVE_EPOLL + PyObject *pyEpoll_Type; +#endif +#ifdef HAVE_KQUEUE + PyObject *kqueue_event_Type; + PyObject *kqueue_queue_Type; +#endif +} selectstate; + + +#define select_state(o) ((selectstate *)PyModule_GetState(o)) + +static int +select_clear(PyObject *m) +{ + selectstate *state = select_state(m); + Py_CLEAR(state->poll_Type); +#ifdef HAVE_SYS_DEVPOLL_H + Py_CLEAR(state->devpoll_Type); +#endif +#ifdef HAVE_EPOLL + Py_CLEAR(state->pyEpoll_Type); +#endif +#ifdef HAVE_KQUEUE + Py_CLEAR(state->kqueue_event_Type); + Py_CLEAR(state->kqueue_queue_Type); +#endif + return 0; +} + +static int +select_traverse(PyObject *m, visitproc visit, void *arg) +{ + selectstate *state = select_state(m); + Py_VISIT(state->poll_Type); +#ifdef HAVE_SYS_DEVPOLL_H + Py_VISIT(state->devpoll_Type); +#endif +#ifdef HAVE_EPOLL + Py_VISIT(state->pyEpoll_Type); +#endif +#ifdef HAVE_KQUEUE + Py_VISIT(state->kqueue_event_Type); + Py_VISIT(state->kqueue_queue_Type); +#endif + return 0; +} + +static void +select_free(void *m) +{ + select_clear((PyObject *)m); +} + +static PyModuleDef selectmodule; + +#define selectstate_global ((selectstate *)PyModule_GetState(PyState_FindModule(&selectmodule))) + + /* list of Python objects and their file descriptor */ typedef struct { PyObject *obj; /* owned reference */ @@ -336,7 +400,6 @@ struct pollfd *ufds; } pollObject; -static PyTypeObject poll_Type; /* Update the malloc'ed array of pollfds to match the dictionary contained within a pollObject. Return 1 on success, 0 on an error. @@ -605,7 +668,8 @@ newPollObject(void) { pollObject *self; - self = PyObject_New(pollObject, &poll_Type); + self = PyObject_New(pollObject, + (PyTypeObject *)selectstate_global->poll_Type); if (self == NULL) return NULL; /* ufd_uptodate is a Boolean, denoting whether the @@ -617,52 +681,44 @@ Py_DECREF(self); return NULL; } + Py_INCREF(selectstate_global->poll_Type); return self; } static void poll_dealloc(pollObject *self) { + PyTypeObject *type = Py_TYPE(self); if (self->ufds != NULL) PyMem_DEL(self->ufds); Py_XDECREF(self->dict); + if((void *)type->tp_dealloc == (void *)poll_dealloc) { + Py_DECREF(type); + } PyObject_Del(self); } -static PyTypeObject poll_Type = { - /* The ob_type field must be initialized in the module init function - * to be portable to Windows without using C++. */ - PyVarObject_HEAD_INIT(NULL, 0) - "select.poll", /*tp_name*/ - sizeof(pollObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)poll_dealloc, /*tp_dealloc*/ - 0, /*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*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - poll_methods, /*tp_methods*/ +/* The ob_type field must be initialized in the module init function +* to be portable to Windows without using C++. */ + + + +static PyType_Slot poll_Type_slots[] = { + {Py_tp_dealloc, (destructor)poll_dealloc}, + {Py_tp_methods, poll_methods}, + {Py_tp_members, }, + {0, 0} }; +static PyType_Spec poll_Type_spec = { + "select.poll", + sizeof(pollObject), + 0, + Py_TPFLAGS_DEFAULT, + poll_Type_slots, +}; + + #ifdef HAVE_SYS_DEVPOLL_H typedef struct { PyObject_HEAD @@ -672,7 +728,6 @@ struct pollfd *fds; } devpollObject; -static PyTypeObject devpoll_Type; static int devpoll_flush(devpollObject *self) { @@ -933,12 +988,14 @@ return NULL; } - self = PyObject_New(devpollObject, &devpoll_Type); + self = PyObject_New(devpollObject, + (PyTypeObject *)selectstate_global->devpoll_Type); if (self == NULL) { close(fd_devpoll); PyMem_DEL(fds); return NULL; } + Py_INCREF(selectstate_global->devpoll_Type); self->fd_devpoll = fd_devpoll; self->max_n_fds = limit.rlim_cur; self->n_fds = 0; @@ -950,48 +1007,40 @@ static void devpoll_dealloc(devpollObject *self) { + PyTypeObject *type = Py_TYPE(self); Py_BEGIN_ALLOW_THREADS close(self->fd_devpoll); Py_END_ALLOW_THREADS + if((void *)type->tp_dealloc == (void *)devpoll_dealloc) { + Py_DECREF(type); + } + PyMem_DEL(self->fds); PyObject_Del(self); } -static PyTypeObject devpoll_Type = { - /* The ob_type field must be initialized in the module init function - * to be portable to Windows without using C++. */ - PyVarObject_HEAD_INIT(NULL, 0) - "select.devpoll", /*tp_name*/ - sizeof(devpollObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)devpoll_dealloc, /*tp_dealloc*/ - 0, /*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*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - devpoll_methods, /*tp_methods*/ +/* The ob_type field must be initialized in the module init function +* to be portable to Windows without using C++. */ + + + +static PyType_Slot devpoll_Type_slots[] = { + {Py_tp_dealloc, (destructor)devpoll_dealloc}, + {Py_tp_methods, devpoll_methods}, + {Py_tp_members, }, + {0, 0} }; + +static PyType_Spec devpoll_Type_spec = { + "select.devpoll", + sizeof(devpollObject), + 0, + Py_TPFLAGS_DEFAULT, + devpoll_Type_slots, +}; + #endif /* HAVE_SYS_DEVPOLL_H */ @@ -1068,8 +1117,7 @@ SOCKET epfd; /* epoll control file descriptor */ } pyEpoll_Object; -static PyTypeObject pyEpoll_Type; -#define pyepoll_CHECK(op) (PyObject_TypeCheck((op), &pyEpoll_Type)) +#define pyepoll_CHECK(op) (PyObject_TypeCheck((op), (PyTypeObject *)selectstate_global->pyEpoll_Type)) static PyObject * pyepoll_err_closed(void) @@ -1146,8 +1194,12 @@ static void pyepoll_dealloc(pyEpoll_Object *self) { + PyTypeObject *type = Py_TYPE(self); (void)pyepoll_internal_close(self); - Py_TYPE(self)->tp_free(self); + type->tp_free(self); + if((void *)type->tp_dealloc == (void *)pyepoll_dealloc) { + Py_DECREF(type); + } } static PyObject* @@ -1434,48 +1486,29 @@ sizehint is used to optimize internal data structures. It doesn't limit\n\ the maximum number of monitored events."); -static PyTypeObject pyEpoll_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "select.epoll", /* tp_name */ - sizeof(pyEpoll_Object), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pyepoll_dealloc, /* tp_dealloc */ - 0, /* 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 */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - pyepoll_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - pyepoll_methods, /* tp_methods */ - 0, /* tp_members */ - pyepoll_getsetlist, /* 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 */ - pyepoll_new, /* tp_new */ - 0, /* tp_free */ + + + +static PyType_Slot pyEpoll_Type_slots[] = { + {Py_tp_dealloc, (destructor)pyepoll_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, pyepoll_doc}, + {Py_tp_methods, pyepoll_methods}, + {Py_tp_getset, pyepoll_getsetlist}, + {Py_tp_new, pyepoll_new}, + {Py_tp_is_gc, }, + {0, 0} }; +static PyType_Spec pyEpoll_Type_spec = { + "select.epoll", + sizeof(pyEpoll_Object), + 0, + Py_TPFLAGS_DEFAULT, + pyEpoll_Type_slots, +}; + + #endif /* HAVE_EPOLL */ #ifdef HAVE_KQUEUE @@ -1532,18 +1565,16 @@ struct kevent e; } kqueue_event_Object; -static PyTypeObject kqueue_event_Type; -#define kqueue_event_Check(op) (PyObject_TypeCheck((op), &kqueue_event_Type)) +#define kqueue_event_Check(op) (PyObject_TypeCheck((op), (PyTypeObject *)selectstate_global->kqueue_event_Type)) typedef struct { PyObject_HEAD SOCKET kqfd; /* kqueue control fd */ } kqueue_queue_Object; -static PyTypeObject kqueue_queue_Type; -#define kqueue_queue_Check(op) (PyObject_TypeCheck((op), &kqueue_queue_Type)) +#define kqueue_queue_Check(op) (PyObject_TypeCheck((op), (PyTypeObject *)selectstate_global->kqueue_queue_Type)) #if (SIZEOF_UINTPTR_T != SIZEOF_VOID_P) # error uintptr_t does not match void *! @@ -1678,48 +1709,28 @@ return PyBool_FromLong((long)result); } -static PyTypeObject kqueue_event_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "select.kevent", /* tp_name */ - sizeof(kqueue_event_Object), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)kqueue_event_repr, /* 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 */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - kqueue_event_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)kqueue_event_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - kqueue_event_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)kqueue_event_init, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ + + + +static PyType_Slot kqueue_event_Type_slots[] = { + {Py_tp_repr, (reprfunc)kqueue_event_repr}, + {Py_tp_doc, kqueue_event_doc}, + {Py_tp_richcompare, (richcmpfunc)kqueue_event_richcompare}, + {Py_tp_members, kqueue_event_members}, + {Py_tp_init, (initproc)kqueue_event_init}, + {Py_tp_is_gc, }, + {0, 0} }; +static PyType_Spec kqueue_event_Type_spec = { + "select.kevent", + sizeof(kqueue_event_Object), + 0, + Py_TPFLAGS_DEFAULT, + kqueue_event_Type_slots, +}; + + static PyObject * kqueue_queue_err_closed(void) { @@ -1771,7 +1782,6 @@ static PyObject * kqueue_queue_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - if ((args != NULL && PyObject_Size(args)) || (kwds != NULL && PyObject_Size(kwds))) { PyErr_SetString(PyExc_ValueError, @@ -1785,8 +1795,12 @@ static void kqueue_queue_dealloc(kqueue_queue_Object *self) { + PyTypeObject *type = Py_TYPE(self); kqueue_queue_internal_close(self); - Py_TYPE(self)->tp_free(self); + type->tp_free(self); + if((void *)type->tp_dealloc == (void *)kqueue_queue_dealloc) { + Py_DECREF(type); + } } static PyObject* @@ -1956,13 +1970,15 @@ for (i = 0; i < gotevents; i++) { kqueue_event_Object *ch; - ch = PyObject_New(kqueue_event_Object, &kqueue_event_Type); + ch = PyObject_New(kqueue_event_Object, + (PyTypeObject *)selectstate_global->kqueue_event_Type); if (ch == NULL) { goto error; } ch->e = evl[i]; PyList_SET_ITEM(result, i, (PyObject *)ch); } + Py_INCREF(selectstate_global->kqueue_event_Type); PyMem_Free(chl); PyMem_Free(evl); return result; @@ -2020,48 +2036,28 @@ To stop listening:\n\ >>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_DELETE)], 0)"); -static PyTypeObject kqueue_queue_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "select.kqueue", /* tp_name */ - sizeof(kqueue_queue_Object), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)kqueue_queue_dealloc, /* tp_dealloc */ - 0, /* 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 */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - kqueue_queue_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - kqueue_queue_methods, /* tp_methods */ - 0, /* tp_members */ - kqueue_queue_getsetlist, /* 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 */ - kqueue_queue_new, /* tp_new */ - 0, /* tp_free */ + + + +static PyType_Slot kqueue_queue_Type_slots[] = { + {Py_tp_dealloc, (destructor)kqueue_queue_dealloc}, + {Py_tp_doc, kqueue_queue_doc}, + {Py_tp_methods, kqueue_queue_methods}, + {Py_tp_getset, kqueue_queue_getsetlist}, + {Py_tp_new, kqueue_queue_new}, + {Py_tp_is_gc, }, + {0, 0} }; +static PyType_Spec kqueue_queue_Type_spec = { + "select.kqueue", + sizeof(kqueue_queue_Object), + 0, + Py_TPFLAGS_DEFAULT, + kqueue_queue_Type_slots, +}; + + #endif /* HAVE_KQUEUE */ @@ -2116,25 +2112,26 @@ PyModuleDef_HEAD_INIT, "select", module_doc, - -1, + sizeof(selectstate), select_methods, NULL, - NULL, - NULL, - NULL + select_traverse, + select_clear, + select_free }; - - - PyMODINIT_FUNC PyInit_select(void) { PyObject *m; + selectstate *state; + m = PyModule_Create(&selectmodule); if (m == NULL) return NULL; + state = select_state(m); + Py_INCREF(PyExc_OSError); PyModule_AddObject(m, "error", PyExc_OSError); @@ -2156,7 +2153,8 @@ #else { #endif - if (PyType_Ready(&poll_Type) < 0) + state->poll_Type = PyType_FromSpec(&poll_Type_spec); + if (state->poll_Type == NULL) return NULL; PyModule_AddIntConstant(m, "POLLIN", POLLIN); PyModule_AddIntConstant(m, "POLLPRI", POLLPRI); @@ -2184,17 +2182,18 @@ #endif /* HAVE_POLL */ #ifdef HAVE_SYS_DEVPOLL_H - if (PyType_Ready(&devpoll_Type) < 0) + state->devpoll_Type = PyType_FromSpec(&devpoll_Type_spec); + if (state->devpoll_Type == NULL) return NULL; #endif #ifdef HAVE_EPOLL - Py_TYPE(&pyEpoll_Type) = &PyType_Type; - if (PyType_Ready(&pyEpoll_Type) < 0) + state->pyEpoll_Type = PyType_FromSpec(&pyEpoll_Type_spec); + if (state->pyEpoll_Type == NULL) return NULL; - Py_INCREF(&pyEpoll_Type); - PyModule_AddObject(m, "epoll", (PyObject *) &pyEpoll_Type); + Py_INCREF(state->pyEpoll_Type); + PyModule_AddObject(m, "epoll", state->pyEpoll_Type); PyModule_AddIntConstant(m, "EPOLLIN", EPOLLIN); PyModule_AddIntConstant(m, "EPOLLOUT", EPOLLOUT); @@ -2219,19 +2218,21 @@ #endif /* HAVE_EPOLL */ #ifdef HAVE_KQUEUE - kqueue_event_Type.tp_new = PyType_GenericNew; - Py_TYPE(&kqueue_event_Type) = &PyType_Type; - if(PyType_Ready(&kqueue_event_Type) < 0) + //kqueue_event_Type.tp_new = PyType_GenericNew; + state->kqueue_event_Type = + PyType_FromSpec(&kqueue_event_Type_spec); + if(state->kqueue_event_Type == NULL) return NULL; - Py_INCREF(&kqueue_event_Type); - PyModule_AddObject(m, "kevent", (PyObject *)&kqueue_event_Type); + Py_INCREF(state->kqueue_event_Type); + PyModule_AddObject(m, "kevent", state->kqueue_event_Type); - Py_TYPE(&kqueue_queue_Type) = &PyType_Type; - if(PyType_Ready(&kqueue_queue_Type) < 0) + state->kqueue_queue_Type = + PyType_FromSpec(&kqueue_queue_Type_spec); + if(state->kqueue_queue_Type == NULL) return NULL; - Py_INCREF(&kqueue_queue_Type); - PyModule_AddObject(m, "kqueue", (PyObject *)&kqueue_queue_Type); + Py_INCREF(state->kqueue_queue_Type); + PyModule_AddObject(m, "kqueue", state->kqueue_queue_Type); /* event filters */ PyModule_AddIntConstant(m, "KQ_FILTER_READ", EVFILT_READ);