Apoyo a la recolección de basura cíclica¶
El soporte de Python para detectar y recolectar basura que involucra referencias circulares requiere el soporte de tipos de objetos que son «contenedores» para otros objetos que también pueden ser contenedores. Los tipos que no almacenan referencias a otros objetos, o que solo almacenan referencias a tipos atómicos (como números o cadenas), no necesitan proporcionar ningún soporte explícito para la recolección de basura.
To create a container type, the tp_flags
field of the type object must
include the Py_TPFLAGS_HAVE_GC
and provide an implementation of the
tp_traverse
handler. If instances of the type are mutable, a
tp_clear
implementation must also be provided.
Py_TPFLAGS_HAVE_GC
Los objetos con un tipo con este indicador establecido deben cumplir con las reglas documentadas aquí. Por conveniencia, estos objetos se denominarán objetos contenedor.
Los constructores para tipos de contenedores deben cumplir con dos reglas:
The memory for the object must be allocated using
PyObject_GC_New
orPyObject_GC_NewVar
.Una vez que se inicializan todos los campos que pueden contener referencias a otros contenedores, debe llamar a
PyObject_GC_Track()
.
Del mismo modo, el desasignador (deallocator) para el objeto debe cumplir con un par similar de reglas:
Antes de invalidar los campos que se refieren a otros contenedores, debe llamarse
PyObject_GC_UnTrack()
.La memoria del objeto debe ser desasignada (deallocated) usando
PyObject_GC_Del()
.Advertencia
Si un tipo añade el Py_TPFLAGS_HAVE_GC, entonces must implementar al menos un manejado
tp_traverse
o usar explícitamente uno de su subclase o subclases.When calling
PyType_Ready()
or some of the APIs that indirectly call it likePyType_FromSpecWithBases()
orPyType_FromSpec()
the interpreter will automatically populate thetp_flags
,tp_traverse
andtp_clear
fields if the type inherits from a class that implements the garbage collector protocol and the child class does not include thePy_TPFLAGS_HAVE_GC
flag.
-
PyObject_GC_New(TYPE, typeobj)¶
Analogous to
PyObject_New
but for container objects with thePy_TPFLAGS_HAVE_GC
flag set.
-
PyObject_GC_NewVar(TYPE, typeobj, size)¶
Analogous to
PyObject_NewVar
but for container objects with thePy_TPFLAGS_HAVE_GC
flag set.
-
PyObject_GC_Resize(TYPE, op, newsize)¶
Resize an object allocated by
PyObject_NewVar
. Returns the resized object of typeTYPE*
(refers to any C type) orNULL
on failure.op must be of type PyVarObject* and must not be tracked by the collector yet. newsize must be of type
Py_ssize_t
.
-
void PyObject_GC_Track(PyObject *op)¶
- Part of the Stable ABI.
Agrega el objeto op al conjunto de objetos contenedor seguidos por el recolector de basura. El recolector puede ejecutarse en momentos inesperados, por lo que los objetos deben ser válidos durante el seguimiento. Esto debería llamarse una vez que todos los campos seguidos por
tp_traverse
se vuelven válidos, generalmente cerca del final del constructor.
-
int PyObject_IS_GC(PyObject *obj)¶
Retorna un valor distinto de cero si el objeto implementa el protocolo del recolector de basura; de lo contrario, retorna 0.
El recolector de basura no puede rastrear el objeto si esta función retorna 0.
-
int PyObject_GC_IsTracked(PyObject *op)¶
- Part of the Stable ABI since version 3.9.
Retorna 1 si el tipo de objeto de op implementa el protocolo GC y el recolector de basura está rastreando op y 0 en caso contrario.
Esto es análogo a la función de Python
gc.is_tracked()
.Nuevo en la versión 3.9.
-
int PyObject_GC_IsFinalized(PyObject *op)¶
- Part of the Stable ABI since version 3.9.
Retorna 1 si el tipo de objeto de op implementa el protocolo GC y op ya ha sido finalizado por el recolector de basura y 0 en caso contrario.
Esto es análogo a la función de Python
gc.is_finalized()
.Nuevo en la versión 3.9.
-
void PyObject_GC_Del(void *op)¶
- Part of the Stable ABI.
Releases memory allocated to an object using
PyObject_GC_New
orPyObject_GC_NewVar
.
-
void PyObject_GC_UnTrack(void *op)¶
- Part of the Stable ABI.
Elimina el objeto op del conjunto de objetos contenedor rastreados por el recolector de basura. Tenga en cuenta que
PyObject_GC_Track()
puede ser llamado nuevamente en este objeto para agregarlo nuevamente al conjunto de objetos rastreados. El desasignador (el manejadortp_dealloc
) debería llamarlo para el objeto antes de que cualquiera de los campos utilizados por el manejadortp_traverse
no sea válido.
Distinto en la versión 3.8: The _PyObject_GC_TRACK()
and _PyObject_GC_UNTRACK()
macros
have been removed from the public C API.
El manejador tp_traverse
acepta un parámetro de función de este tipo:
-
typedef int (*visitproc)(PyObject *object, void *arg)¶
- Part of the Stable ABI.
Tipo de la función visitante que se pasa al manejador
tp_traverse
. La función debe llamarse con un objeto para atravesar como object y el tercer parámetro para el manejadortp_traverse
como arg. El núcleo de Python utiliza varias funciones visitantes para implementar la detección de basura cíclica; No se espera que los usuarios necesiten escribir sus propias funciones visitante.
El manejador tp_traverse
debe tener el siguiente tipo:
-
typedef int (*traverseproc)(PyObject *self, visitproc visit, void *arg)¶
- Part of the Stable ABI.
Función transversal para un objeto contenedor. Las implementaciones deben llamar a la función visit para cada objeto directamente contenido por self, siendo los parámetros a visit el objeto contenido y el valor arg pasado al controlador. La función visit no debe llamarse con un argumento de objeto
NULL
. Si visit retorna un valor distinto de cero, ese valor debe retornarse inmediatamente.
Para simplificar la escritura de los manejadores tp_traverse
, se proporciona un macro a Py_VISIT()
. Para usar este macro, la implementación tp_traverse
debe nombrar sus argumentos exactamente visit y arg:
-
void Py_VISIT(PyObject *o)¶
Si o no es
NULL
, llama a la devolución de llamada (callback) visit, con argumentos o y arg. Si visit retorna un valor distinto de cero, lo retorna. Usando este macro, los manejadorestp_traverse
tienen el siguiente aspecto:static int my_traverse(Noddy *self, visitproc visit, void *arg) { Py_VISIT(self->foo); Py_VISIT(self->bar); return 0; }
El manejador tp_clear
debe ser del tipo query
, o NULL
si el objeto es inmutable.
-
typedef int (*inquiry)(PyObject *self)¶
- Part of the Stable ABI.
Descarta referencias que pueden haber creado ciclos de referencia. Los objetos inmutables no tienen que definir este método ya que nunca pueden crear directamente ciclos de referencia. Tenga en cuenta que el objeto aún debe ser válido después de llamar a este método (no solo llame a
Py_DECREF()
en una referencia). El recolector de basura llamará a este método si detecta que este objeto está involucrado en un ciclo de referencia.
Controlar el estado del recolector de basura¶
La C-API proporciona las siguientes funciones para controlar las ejecuciones de recolección de basura.
-
Py_ssize_t PyGC_Collect(void)¶
- Part of the Stable ABI.
Realiza una recolección de basura completa, si el recolector de basura está habilitado. (Tenga en cuenta que
gc.collect()
lo ejecuta incondicionalmente).Retorna el número de objetos recolectados e inalcanzables que no se pueden recolectar. Si el recolector de basura está deshabilitado o ya está recolectando, retorna
0
inmediatamente. Los errores durante la recolección de basura se pasan asys.unraisablehook
. Esta función no genera excepciones.
-
int PyGC_Enable(void)¶
- Part of the Stable ABI since version 3.10.
Habilita el recolector de basura: similar a
gc.enable()
. Retorna el estado anterior, 0 para deshabilitado y 1 para habilitado.Nuevo en la versión 3.10.
-
int PyGC_Disable(void)¶
- Part of the Stable ABI since version 3.10.
Deshabilita el recolector de basura: similar a
gc.disable()
. Retorna el estado anterior, 0 para deshabilitado y 1 para habilitado.Nuevo en la versión 3.10.
-
int PyGC_IsEnabled(void)¶
- Part of the Stable ABI since version 3.10.
Consulta el estado del recolector de basura: similar a
gc.isenabled()
. Retorna el estado actual, 0 para deshabilitado y 1 para habilitado.Nuevo en la versión 3.10.