diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst index 82277aa52ae..e36a71af2b6 100644 --- a/Doc/library/gc.rst +++ b/Doc/library/gc.rst @@ -96,7 +96,7 @@ The :mod:`gc` module provides the following functions: .. versionadded:: 3.4 -.. function:: set_threshold(threshold0[, threshold1[, threshold2]]) +.. function:: set_threshold(threshold0, [threshold1, [threshold2]]) Set the garbage collection thresholds (the collection frequency). Setting *threshold0* to zero disables collection. diff --git a/Modules/clinic/gcmodule.c.h b/Modules/clinic/gcmodule.c.h index ad446935044..d50d170589a 100644 --- a/Modules/clinic/gcmodule.c.h +++ b/Modules/clinic/gcmodule.c.h @@ -214,6 +214,58 @@ exit: return return_value; } +PyDoc_STRVAR(gc_set_threshold__doc__, +"set_threshold(threshold0, [threshold1, [threshold2]])\n" +"Set the collection thresholds (the collection frequency).\n" +"\n" +"Setting \'threshold0\' to zero disables collection."); + +#define GC_SET_THRESHOLD_METHODDEF \ + {"set_threshold", (PyCFunction)gc_set_threshold, METH_VARARGS, gc_set_threshold__doc__}, + +static PyObject * +gc_set_threshold_impl(PyObject *module, int threshold0, int group_right_1, + int threshold1, int group_right_2, int threshold2); + +static PyObject * +gc_set_threshold(PyObject *module, PyObject *args) +{ + PyObject *return_value = NULL; + int threshold0; + int group_right_1 = 0; + int threshold1 = 0; + int group_right_2 = 0; + int threshold2 = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "i:set_threshold", &threshold0)) { + goto exit; + } + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:set_threshold", &threshold0, &threshold1)) { + goto exit; + } + group_right_1 = 1; + break; + case 3: + if (!PyArg_ParseTuple(args, "iii:set_threshold", &threshold0, &threshold1, &threshold2)) { + goto exit; + } + group_right_1 = 1; + group_right_2 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "gc.set_threshold requires 1 to 3 arguments"); + goto exit; + } + return_value = gc_set_threshold_impl(module, threshold0, group_right_1, threshold1, group_right_2, threshold2); + +exit: + return return_value; +} + PyDoc_STRVAR(gc_get_threshold__doc__, "get_threshold($module, /)\n" "--\n" @@ -250,6 +302,76 @@ gc_get_count(PyObject *module, PyObject *Py_UNUSED(ignored)) return gc_get_count_impl(module); } +PyDoc_STRVAR(gc_get_referrers__doc__, +"get_referrers($module, /, *objs)\n" +"--\n" +"\n" +"Return the list of objects that directly refer to any of \'objs\'."); + +#define GC_GET_REFERRERS_METHODDEF \ + {"get_referrers", _PyCFunction_CAST(gc_get_referrers), METH_FASTCALL, gc_get_referrers__doc__}, + +static PyObject * +gc_get_referrers_impl(PyObject *module, PyObject *args); + +static PyObject * +gc_get_referrers(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("get_referrers", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = gc_get_referrers_impl(module, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + +PyDoc_STRVAR(gc_get_referents__doc__, +"get_referents($module, /, *objs)\n" +"--\n" +"\n" +"Return the list of objects that are directly referred to by \'objs\'."); + +#define GC_GET_REFERENTS_METHODDEF \ + {"get_referents", _PyCFunction_CAST(gc_get_referents), METH_FASTCALL, gc_get_referents__doc__}, + +static PyObject * +gc_get_referents_impl(PyObject *module, PyObject *args); + +static PyObject * +gc_get_referents(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("get_referents", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = gc_get_referents_impl(module, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(gc_get_objects__doc__, "get_objects($module, /, generation=None)\n" "--\n" @@ -425,4 +547,4 @@ gc_get_freeze_count(PyObject *module, PyObject *Py_UNUSED(ignored)) exit: return return_value; } -/*[clinic end generated code: output=5c345e7b4ce6085a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=258f92524c1141fc input=a9049054013a1b77]*/ diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 9a827cb79d7..ffddef34ecc 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -134,24 +134,41 @@ gc_get_debug_impl(PyObject *module) return gcstate->debug; } -PyDoc_STRVAR(gc_set_thresh__doc__, -"set_threshold(threshold0, [threshold1, threshold2]) -> None\n" -"\n" -"Sets the collection thresholds. Setting threshold0 to zero disables\n" -"collection.\n"); +/*[clinic input] +gc.set_threshold + + threshold0: int + [ + threshold1: int + [ + threshold2: int + ] + ] + / + +Set the collection thresholds (the collection frequency). + +Setting 'threshold0' to zero disables collection. +[clinic start generated code]*/ static PyObject * -gc_set_threshold(PyObject *self, PyObject *args) +gc_set_threshold_impl(PyObject *module, int threshold0, int group_right_1, + int threshold1, int group_right_2, int threshold2) +/*[clinic end generated code: output=2e3c7c7dd59060f3 input=0d9612db50984eec]*/ { GCState *gcstate = get_gc_state(); - if (!PyArg_ParseTuple(args, "i|ii:set_threshold", - &gcstate->generations[0].threshold, - &gcstate->generations[1].threshold, - &gcstate->generations[2].threshold)) - return NULL; - for (int i = 3; i < NUM_GENERATIONS; i++) { + + gcstate->generations[0].threshold = threshold0; + if (group_right_1) { + gcstate->generations[1].threshold = threshold1; + } + if (group_right_2) { + gcstate->generations[2].threshold = threshold2; + /* generations higher than 2 get the same threshold */ - gcstate->generations[i].threshold = gcstate->generations[2].threshold; + for (int i = 3; i < NUM_GENERATIONS; i++) { + gcstate->generations[i].threshold = gcstate->generations[2].threshold; + } } Py_RETURN_NONE; } @@ -190,12 +207,17 @@ gc_get_count_impl(PyObject *module) gcstate->generations[2].count); } -PyDoc_STRVAR(gc_get_referrers__doc__, -"get_referrers(*objs) -> list\n\ -Return the list of objects that directly refer to any of objs."); +/*[clinic input] +gc.get_referrers + + *objs as args: object + +Return the list of objects that directly refer to any of 'objs'. +[clinic start generated code]*/ static PyObject * -gc_get_referrers(PyObject *self, PyObject *args) +gc_get_referrers_impl(PyObject *module, PyObject *args) +/*[clinic end generated code: output=296a09587f6a86b5 input=bae96961b14a0922]*/ { if (PySys_Audit("gc.get_referrers", "(O)", args) < 0) { return NULL; @@ -213,12 +235,17 @@ referentsvisit(PyObject *obj, void *arg) return PyList_Append(list, obj) < 0; } -PyDoc_STRVAR(gc_get_referents__doc__, -"get_referents(*objs) -> list\n\ -Return the list of objects that are directly referred to by objs."); +/*[clinic input] +gc.get_referents + + *objs as args: object + +Return the list of objects that are directly referred to by 'objs'. +[clinic start generated code]*/ static PyObject * -gc_get_referents(PyObject *self, PyObject *args) +gc_get_referents_impl(PyObject *module, PyObject *args) +/*[clinic end generated code: output=d47dc02cefd06fe8 input=b3ceab0c34038cbf]*/ { Py_ssize_t i; if (PySys_Audit("gc.get_referents", "(O)", args) < 0) { @@ -453,17 +480,15 @@ static PyMethodDef GcMethods[] = { GC_SET_DEBUG_METHODDEF GC_GET_DEBUG_METHODDEF GC_GET_COUNT_METHODDEF - {"set_threshold", gc_set_threshold, METH_VARARGS, gc_set_thresh__doc__}, + GC_SET_THRESHOLD_METHODDEF GC_GET_THRESHOLD_METHODDEF GC_COLLECT_METHODDEF GC_GET_OBJECTS_METHODDEF GC_GET_STATS_METHODDEF GC_IS_TRACKED_METHODDEF GC_IS_FINALIZED_METHODDEF - {"get_referrers", gc_get_referrers, METH_VARARGS, - gc_get_referrers__doc__}, - {"get_referents", gc_get_referents, METH_VARARGS, - gc_get_referents__doc__}, + GC_GET_REFERRERS_METHODDEF + GC_GET_REFERENTS_METHODDEF GC_FREEZE_METHODDEF GC_UNFREEZE_METHODDEF GC_GET_FREEZE_COUNT_METHODDEF