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:

1. The memory for the object must be allocated using "PyObject_GC_New"
   or "PyObject_GC_NewVar".

2. 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:

1. Antes de invalidar los campos que se refieren a otros contenedores,
   debe llamarse "PyObject_GC_UnTrack()".

2. 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 like
     "PyType_FromSpecWithBases()" or "PyType_FromSpec()" the
     interpreter will automatically populate the "tp_flags",
     "tp_traverse" and "tp_clear" fields if the type inherits from a
     class that implements the garbage collector protocol and the
     child class does *not* include the "Py_TPFLAGS_HAVE_GC" flag.

PyObject_GC_New(TYPE, typeobj)

   Analogous to "PyObject_New" but for container objects with the
   "Py_TPFLAGS_HAVE_GC" flag set.

PyObject_GC_NewVar(TYPE, typeobj, size)

   Analogous to "PyObject_NewVar" but for container objects with the
   "Py_TPFLAGS_HAVE_GC" flag set.

PyObject *PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size)

   *This is Unstable API. It may change without warning in minor
   releases.*

   Analogous to "PyObject_GC_New" but allocates *extra_size* bytes at
   the end of the object (at offset "tp_basicsize"). The allocated
   memory is initialized to zeros, except for the "Python object
   header".

   The extra data will be deallocated with the object, but otherwise
   it is not managed by Python.

   Advertencia:

     The function is marked as unstable because the final mechanism
     for reserving extra data after an instance is not yet decided.
     For allocating a variable number of fields, prefer using
     "PyVarObject" and "tp_itemsize" instead.

   Added in version 3.12.

PyObject_GC_Resize(TYPE, op, newsize)

   Resize an object allocated by "PyObject_NewVar". Returns the
   resized object of type "TYPE*" (refers to any C type) or "NULL" 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()".

   Added in version 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()".

   Added in version 3.9.

void PyObject_GC_Del(void *op)
    * Part of the Stable ABI.*

   Releases memory allocated to an object using "PyObject_GC_New" or
   "PyObject_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 manejador "tp_dealloc") debería llamarlo para el
   objeto antes de que cualquiera de los campos utilizados por el
   manejador "tp_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 manejador
   "tp_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 manejadores
   "tp_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 a "sys.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.

   Added in version 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.

   Added in version 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.

   Added in version 3.10.


Querying Garbage Collector State
================================

The C-API provides the following interface for querying information
about the garbage collector.

void PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg)

   *This is Unstable API. It may change without warning in minor
   releases.*

   Run supplied *callback* on all live GC-capable objects. *arg* is
   passed through to all invocations of *callback*.

   Advertencia:

     If new objects are (de)allocated by the callback it is undefined
     if they will be visited.Garbage collection is disabled during
     operation. Explicitly running a collection in the callback may
     lead to undefined behaviour e.g. visiting the same objects
     multiple times or not at all.

   Added in version 3.12.

typedef int (*gcvisitobjects_t)(PyObject *object, void *arg)

   Type of the visitor function to be passed to
   "PyUnstable_GC_VisitObjects()". *arg* is the same as the *arg*
   passed to "PyUnstable_GC_VisitObjects". Return "1" to continue
   iteration, return "0" to stop iteration. Other return values are
   reserved for now so behavior on returning anything else is
   undefined.

   Added in version 3.12.
