| To: vim_dev@googlegroups.com |
| Subject: Patch 7.3.965 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 7.3.965 |
| Problem: Python garbage collection not working properly. |
| Solution: Add support for garbage collection. (ZyX) |
| Files: src/if_py_both.h |
| |
| |
| |
| |
| |
| *** 543,548 **** |
| --- 543,550 ---- |
| |
| typedef PyObject *(*nextfun)(void **); |
| typedef void (*destructorfun)(void *); |
| + typedef int (*traversefun)(void *, visitproc, void *); |
| + typedef int (*clearfun)(void **); |
| |
| /* Main purpose of this object is removing the need for do python initialization |
| * (i.e. PyType_Ready and setting type attributes) for a big bunch of objects. |
| |
| *** 554,563 **** |
| void *cur; |
| nextfun next; |
| destructorfun destruct; |
| } IterObject; |
| |
| static PyObject * |
| ! IterNew(void *start, destructorfun destruct, nextfun next) |
| { |
| IterObject *self; |
| |
| --- 556,568 ---- |
| void *cur; |
| nextfun next; |
| destructorfun destruct; |
| + traversefun traverse; |
| + clearfun clear; |
| } IterObject; |
| |
| static PyObject * |
| ! IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse, |
| ! clearfun clear) |
| { |
| IterObject *self; |
| |
| |
| *** 565,570 **** |
| --- 570,577 ---- |
| self->cur = start; |
| self->next = next; |
| self->destruct = destruct; |
| + self->traverse = traverse; |
| + self->clear = clear; |
| |
| return (PyObject *)(self); |
| } |
| |
| *** 579,584 **** |
| --- 586,613 ---- |
| DESTRUCTOR_FINISH(self); |
| } |
| |
| + static int |
| + IterTraverse(PyObject *self, visitproc visit, void *arg) |
| + { |
| + IterObject *this = (IterObject *)(self); |
| + |
| + if (this->traverse != NULL) |
| + return this->traverse(this->cur, visit, arg); |
| + else |
| + return 0; |
| + } |
| + |
| + static int |
| + IterClear(PyObject *self) |
| + { |
| + IterObject *this = (IterObject *)(self); |
| + |
| + if (this->clear != NULL) |
| + return this->clear(&this->cur); |
| + else |
| + return 0; |
| + } |
| + |
| static PyObject * |
| IterNext(PyObject *self) |
| { |
| |
| *** 1034,1040 **** |
| lii->list = l; |
| |
| return IterNew(lii, |
| ! (destructorfun) ListIterDestruct, (nextfun) ListIterNext); |
| } |
| |
| static int |
| --- 1063,1070 ---- |
| lii->list = l; |
| |
| return IterNew(lii, |
| ! (destructorfun) ListIterDestruct, (nextfun) ListIterNext, |
| ! NULL, NULL); |
| } |
| |
| static int |
| |
| *** 1348,1353 **** |
| --- 1378,1430 ---- |
| PyObject *fromObj; |
| } OptionsObject; |
| |
| + static int |
| + dummy_check(void *arg UNUSED) |
| + { |
| + return 0; |
| + } |
| + |
| + static PyObject * |
| + OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj) |
| + { |
| + OptionsObject *self; |
| + |
| + self = PyObject_NEW(OptionsObject, &OptionsType); |
| + if (self == NULL) |
| + return NULL; |
| + |
| + self->opt_type = opt_type; |
| + self->from = from; |
| + self->Check = Check; |
| + self->fromObj = fromObj; |
| + if (fromObj) |
| + Py_INCREF(fromObj); |
| + |
| + return (PyObject *)(self); |
| + } |
| + |
| + static void |
| + OptionsDestructor(PyObject *self) |
| + { |
| + if (((OptionsObject *)(self))->fromObj) |
| + Py_DECREF(((OptionsObject *)(self))->fromObj); |
| + DESTRUCTOR_FINISH(self); |
| + } |
| + |
| + static int |
| + OptionsTraverse(PyObject *self, visitproc visit, void *arg) |
| + { |
| + Py_VISIT(((OptionsObject *)(self))->fromObj); |
| + return 0; |
| + } |
| + |
| + static int |
| + OptionsClear(PyObject *self) |
| + { |
| + Py_CLEAR(((OptionsObject *)(self))->fromObj); |
| + return 0; |
| + } |
| + |
| static PyObject * |
| OptionsItem(OptionsObject *this, PyObject *keyObject) |
| { |
| |
| *** 1562,1600 **** |
| return r; |
| } |
| |
| - static int |
| - dummy_check(void *arg UNUSED) |
| - { |
| - return 0; |
| - } |
| - |
| - static PyObject * |
| - OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj) |
| - { |
| - OptionsObject *self; |
| - |
| - self = PyObject_NEW(OptionsObject, &OptionsType); |
| - if (self == NULL) |
| - return NULL; |
| - |
| - self->opt_type = opt_type; |
| - self->from = from; |
| - self->Check = Check; |
| - self->fromObj = fromObj; |
| - if (fromObj) |
| - Py_INCREF(fromObj); |
| - |
| - return (PyObject *)(self); |
| - } |
| - |
| - static void |
| - OptionsDestructor(PyObject *self) |
| - { |
| - if (((OptionsObject *)(self))->fromObj) |
| - Py_DECREF(((OptionsObject *)(self))->fromObj); |
| - DESTRUCTOR_FINISH(self); |
| - } |
| - |
| static PyMappingMethods OptionsAsMapping = { |
| (lenfunc) NULL, |
| (binaryfunc) OptionsItem, |
| --- 1639,1644 ---- |
| |
| *** 1843,1848 **** |
| --- 1887,1905 ---- |
| else |
| return firstwin; |
| } |
| + static int |
| + WindowTraverse(PyObject *self, visitproc visit, void *arg) |
| + { |
| + Py_VISIT(((PyObject *)(((WindowObject *)(self))->tabObject))); |
| + return 0; |
| + } |
| + |
| + static int |
| + WindowClear(PyObject *self) |
| + { |
| + Py_CLEAR((((WindowObject *)(self))->tabObject)); |
| + return 0; |
| + } |
| |
| static PyObject * |
| WindowAttr(WindowObject *this, char *name) |
| |
| *** 3193,3198 **** |
| --- 3250,3269 ---- |
| } |
| } |
| |
| + static int |
| + BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg) |
| + { |
| + Py_VISIT(buffer); |
| + return 0; |
| + } |
| + |
| + static int |
| + BufMapIterClear(PyObject **buffer) |
| + { |
| + Py_CLEAR(*buffer); |
| + return 0; |
| + } |
| + |
| static PyObject * |
| BufMapIterNext(PyObject **buffer) |
| { |
| |
| *** 3228,3234 **** |
| |
| buffer = BufferNew(firstbuf); |
| return IterNew(buffer, |
| ! (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext); |
| } |
| |
| static PyMappingMethods BufMapAsMapping = { |
| --- 3299,3306 ---- |
| |
| buffer = BufferNew(firstbuf); |
| return IterNew(buffer, |
| ! (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext, |
| ! (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear); |
| } |
| |
| static PyMappingMethods BufMapAsMapping = { |
| |
| *** 3837,3842 **** |
| --- 3909,3916 ---- |
| IterType.tp_iter = IterIter; |
| IterType.tp_iternext = IterNext; |
| IterType.tp_dealloc = IterDestructor; |
| + IterType.tp_traverse = IterTraverse; |
| + IterType.tp_clear = IterClear; |
| |
| vim_memset(&BufferType, 0, sizeof(BufferType)); |
| BufferType.tp_name = "vim.buffer"; |
| |
| *** 3865,3870 **** |
| --- 3939,3946 ---- |
| WindowType.tp_flags = Py_TPFLAGS_DEFAULT; |
| WindowType.tp_doc = "vim Window object"; |
| WindowType.tp_methods = WindowMethods; |
| + WindowType.tp_traverse = WindowTraverse; |
| + WindowType.tp_clear = WindowClear; |
| #if PY_MAJOR_VERSION >= 3 |
| WindowType.tp_getattro = WindowGetattro; |
| WindowType.tp_setattro = WindowSetattro; |
| |
| *** 4003,4008 **** |
| --- 4079,4086 ---- |
| OptionsType.tp_doc = "object for manipulating options"; |
| OptionsType.tp_as_mapping = &OptionsAsMapping; |
| OptionsType.tp_dealloc = OptionsDestructor; |
| + OptionsType.tp_traverse = OptionsTraverse; |
| + OptionsType.tp_clear = OptionsClear; |
| |
| #if PY_MAJOR_VERSION >= 3 |
| vim_memset(&vimmodule, 0, sizeof(vimmodule)); |
| |
| |
| |
| *** 730,731 **** |
| --- 730,733 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 965, |
| /**/ |
| |
| -- |
| ARTHUR: Charge! |
| [They all charge with swords drawn towards the RABBIT. A tremendous twenty |
| second fight with Peckinpahish shots and borrowing heavily also on the |
| Kung Fu and karate-type films ensues, in which some four KNIGHTS are |
| comprehensively killed.] |
| ARTHUR: Run away! Run away! |
| "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ |
| /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ |
| \\\ an exciting new programming language -- http://www.Zimbu.org /// |
| \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |