Index: Doc/lib/libgc.tex =================================================================== --- Doc/lib/libgc.tex (revision 42877) +++ Doc/lib/libgc.tex (working copy) @@ -32,9 +32,11 @@ Returns true if automatic collection is enabled. \end{funcdesc} -\begin{funcdesc}{collect}{} -Run a full collection. All generations are examined and the -number of unreachable objects found is returned. +\begin{funcdesc}{collect}{\optional{generation}} +With no arguments, run a full collection. The optional argument +\var{generation} may be an integer specifying which generation to collect +(from 0 to 2). A ValueError is raised if the generation number is invalid. +The number of unreachable objects found is returned. \end{funcdesc} \begin{funcdesc}{set_debug}{flags} @@ -76,6 +78,11 @@ \code{1} before collecting generation \code{2}. \end{funcdesc} +\begin{funcdesc}{get_count}{} +Return the current collection counts as a tuple of +\code{(\var{count0}, \var{count1}, \var{count2})}. +\end{funcdesc} + \begin{funcdesc}{get_threshold}{} Return the current collection thresholds as a tuple of \code{(\var{threshold0}, \var{threshold1}, \var{threshold2})}. Index: Lib/test/test_gc.py =================================================================== --- Lib/test/test_gc.py (revision 42877) +++ Lib/test/test_gc.py (working copy) @@ -219,6 +219,22 @@ gc.disable() gc.set_threshold(*thresholds) +def test_get_count(): + gc.collect() + expect(gc.get_count(), (0, 0, 0), "get_count()") + a = dict() + expect(gc.get_count(), (1, 0, 0), "get_count()") + +def test_collect_generations(): + gc.collect() + a = dict() + gc.collect(0) + expect(gc.get_count(), (0, 1, 0), "collect(0)") + gc.collect(1) + expect(gc.get_count(), (0, 0, 1), "collect(1)") + gc.collect(2) + expect(gc.get_count(), (0, 0, 0), "collect(1)") + class Ouch: n = 0 def __del__(self): @@ -571,6 +587,8 @@ run_test("finalizers (new class)", test_finalizer_newclass) run_test("__del__", test_del) run_test("__del__ (new class)", test_del_newclass) + run_test("get_count()", test_get_count) + run_test("collect(n)", test_collect_generations) run_test("saveall", test_saveall) run_test("trashcan", test_trashcan) run_test("boom", test_boom) Index: Modules/gcmodule.c =================================================================== --- Modules/gcmodule.c (revision 42877) +++ Modules/gcmodule.c (working copy) @@ -925,20 +925,33 @@ } PyDoc_STRVAR(gc_collect__doc__, -"collect() -> n\n" +"collect([generation]) -> n\n" "\n" -"Run a full collection. The number of unreachable objects is returned.\n"); +"With no arguments, run a full collection. The optional argument\n" +"may be an integer specifying which generation to collect. A ValueError\n" +"is raised if the generation number is invalid.\n\n" +"The number of unreachable objects is returned.\n"); static PyObject * -gc_collect(PyObject *self, PyObject *noargs) +gc_collect(PyObject *self, PyObject *args, PyObject *kws) { + static char *keywords[] = {"generation", NULL}; + int genarg = NUM_GENERATIONS - 1; Py_ssize_t n; + if (!PyArg_ParseTupleAndKeywords(args, kws, "|i", keywords, &genarg)) + return NULL; + + else if (genarg < 0 || genarg >= NUM_GENERATIONS) { + PyErr_SetString(PyExc_ValueError, "invalid generation"); + return NULL; + } + if (collecting) n = 0; /* already collecting, don't do anything */ else { collecting = 1; - n = collect(NUM_GENERATIONS - 1); + n = collect(genarg); collecting = 0; } @@ -1020,6 +1033,20 @@ generations[2].threshold); } +PyDoc_STRVAR(gc_get_count__doc__, +"get_count() -> (count0, count1, count2)\n" +"\n" +"Return the current collection counts\n"); + +static PyObject * +gc_get_count(PyObject *self, PyObject *noargs) +{ + return Py_BuildValue("(iii)", + generations[0].count, + generations[1].count, + generations[2].count); +} + static int referrersvisit(PyObject* obj, PyObject *objs) { @@ -1150,9 +1177,11 @@ {"isenabled", gc_isenabled, METH_NOARGS, gc_isenabled__doc__}, {"set_debug", gc_set_debug, METH_VARARGS, gc_set_debug__doc__}, {"get_debug", gc_get_debug, METH_NOARGS, gc_get_debug__doc__}, + {"get_count", gc_get_count, METH_NOARGS, gc_get_count__doc__}, {"set_threshold", gc_set_thresh, METH_VARARGS, gc_set_thresh__doc__}, {"get_threshold", gc_get_thresh, METH_NOARGS, gc_get_thresh__doc__}, - {"collect", gc_collect, METH_NOARGS, gc_collect__doc__}, + {"collect", (PyCFunction)gc_collect, + METH_VARARGS | METH_KEYWORDS, gc_collect__doc__}, {"get_objects", gc_get_objects,METH_NOARGS, gc_get_objects__doc__}, {"get_referrers", gc_get_referrers, METH_VARARGS, gc_get_referrers__doc__},