Kaydet (Commit) 259272b7 authored tarafından Tim Peters's avatar Tim Peters

handle_finalizers(): Rewrote to call append_objects() and gc_list_merge()

instead of looping.  Smaller and clearer.  Faster, too, when we're not
appending to gc.garbage:  gc_list_merge() takes constant time, regardless
of the lists' sizes.

append_objects():  Moved up to live with the other list manipulation
utilities.
üst f394df47
...@@ -182,6 +182,24 @@ gc_list_size(PyGC_Head *list) ...@@ -182,6 +182,24 @@ gc_list_size(PyGC_Head *list)
return n; return n;
} }
/* Append objects in a GC list to a Python list.
* Return 0 if all OK, < 0 if error (out of memory for list).
*/
static int
append_objects(PyObject *py_list, PyGC_Head *gc_list)
{
PyGC_Head *gc;
for (gc = gc_list->gc.gc_next; gc != gc_list; gc = gc->gc.gc_next) {
PyObject *op = FROM_GC(gc);
if (op != py_list) {
if (PyList_Append(py_list, op)) {
return -1; /* exception */
}
}
}
return 0;
}
/*** end of list stuff ***/ /*** end of list stuff ***/
...@@ -457,33 +475,26 @@ debug_cycle(char *msg, PyObject *op) ...@@ -457,33 +475,26 @@ debug_cycle(char *msg, PyObject *op)
/* Handle uncollectable garbage (cycles with finalizers, and stuff reachable /* Handle uncollectable garbage (cycles with finalizers, and stuff reachable
* only from such cycles). * only from such cycles).
* If DEBUG_SAVEALL or hasfinalizer, the objects in finalizers are appended
* to the module garbage list (a Python list). The objects in finalizers
* are merged into the old list regardless.
* Returns 0 if all OK, <0 on error (out of memory to grow the garbage list).
* The finalizers list is made empty on a successful return.
*/ */
static void static int
handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old, int hasfinalizer) handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old, int hasfinalizer)
{ {
PyGC_Head *gc;
if (garbage == NULL) { if (garbage == NULL) {
garbage = PyList_New(0); garbage = PyList_New(0);
if (garbage == NULL) if (garbage == NULL)
Py_FatalError("gc couldn't create gc.garbage list"); Py_FatalError("gc couldn't create gc.garbage list");
} }
for (gc = finalizers->gc.gc_next; if ((debug & DEBUG_SAVEALL) || hasfinalizer) {
gc != finalizers; if (append_objects(garbage, finalizers) < 0)
gc = finalizers->gc.gc_next) { return -1;
PyObject *op = FROM_GC(gc);
assert(IS_REACHABLE(op));
if ((debug & DEBUG_SAVEALL) || hasfinalizer) {
/* If SAVEALL is not set then just append objects with
* finalizers to the list of garbage. All objects in
* the finalizers list are reachable from those
* objects.
*/
PyList_Append(garbage, op);
}
gc_list_remove(gc);
gc_list_append(gc, old);
} }
gc_list_merge(finalizers, old);
return 0;
} }
/* Break reference cycles by clearing the containers involved. This is /* Break reference cycles by clearing the containers involved. This is
...@@ -662,8 +673,8 @@ collect(int generation) ...@@ -662,8 +673,8 @@ collect(int generation)
* reachable list of garbage. The programmer has to deal with * reachable list of garbage. The programmer has to deal with
* this if they insist on creating this type of structure. * this if they insist on creating this type of structure.
*/ */
handle_finalizers(&finalizers, old, 1); if (handle_finalizers(&finalizers, old, 1) == 0)
handle_finalizers(&reachable_from_finalizers, old, 0); (void)handle_finalizers(&reachable_from_finalizers, old, 0);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
if (gc_str == NULL) { if (gc_str == NULL) {
...@@ -907,22 +918,6 @@ PyDoc_STRVAR(gc_get_objects__doc__, ...@@ -907,22 +918,6 @@ PyDoc_STRVAR(gc_get_objects__doc__,
"Return a list of objects tracked by the collector (excluding the list\n" "Return a list of objects tracked by the collector (excluding the list\n"
"returned).\n"); "returned).\n");
/* appending objects in a GC list to a Python list */
static int
append_objects(PyObject *py_list, PyGC_Head *gc_list)
{
PyGC_Head *gc;
for (gc = gc_list->gc.gc_next; gc != gc_list; gc = gc->gc.gc_next) {
PyObject *op = FROM_GC(gc);
if (op != py_list) {
if (PyList_Append(py_list, op)) {
return -1; /* exception */
}
}
}
return 0;
}
static PyObject * static PyObject *
gc_get_objects(PyObject *self, PyObject *noargs) gc_get_objects(PyObject *self, PyObject *noargs)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment