diff options
-rw-r--r-- | Doc/lib/libgc.tex | 16 | ||||
-rw-r--r-- | Lib/test/test_gc.py | 18 | ||||
-rw-r--r-- | Misc/NEWS | 5 | ||||
-rw-r--r-- | Modules/gcmodule.c | 39 |
4 files changed, 69 insertions, 9 deletions
diff --git a/Doc/lib/libgc.tex b/Doc/lib/libgc.tex index e53e2a8..54ca26c 100644 --- a/Doc/lib/libgc.tex +++ b/Doc/lib/libgc.tex @@ -32,9 +32,13 @@ Disable automatic garbage collection. 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. + +\versionchanged[The optional \var{generation} argument was added]{2.5} \end{funcdesc} \begin{funcdesc}{set_debug}{flags} @@ -76,6 +80,12 @@ examined, then generation \code{1} is examined as well. Similarly, \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})}. +\versionadded{2.5} +\end{funcdesc} + \begin{funcdesc}{get_threshold}{} Return the current collection thresholds as a tuple of \code{(\var{threshold0}, \var{threshold1}, \var{threshold2})}. diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index fa8659e..ec470c4 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -219,6 +219,22 @@ def test_del_newclass(): 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 @@ def test_all(): 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) @@ -78,7 +78,7 @@ Core and builtins This was not portable. float('0x3') now raises a ValueError. - Patch #1382163: Expose Subversion revision number to Python. New C API - function Py_GetBuildNumber(). New attribute sys.build_number. Build number + function Py_GetBuildNumber(). New attribute sys.subversion. Build number is now displayed in interactive prompt banner. - Implementation of PEP 341 - Unification of try/except and try/finally. @@ -427,6 +427,9 @@ Extension Modules Library ------- +- The function get_count() has been added to the gc module, and gc.collect() + grew an optional 'generation' argument. + - A library msilib to generate Windows Installer files, and a distutils command bdist_msi have been added. diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index a3655d6..7e3f95a 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -925,20 +925,33 @@ gc_isenabled(PyObject *self, PyObject *noargs) } 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 @@ gc_get_thresh(PyObject *self, PyObject *noargs) 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 @@ static PyMethodDef GcMethods[] = { {"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__}, |