使对象类型支持循环垃圾回收
**************************

Python 对循环引用的垃圾检测与回收需要“容器”对象类型的支持，此类型的容
器对象中可能包含其它容器对象。不保存其它对象的引用的类型，或者只保存原
子类型（如数字或字符串）的引用的类型，不需要显式提供垃圾回收的支持。

要创建一个容器类，类型对象的 "tp_flags" 字段必须包括
"Py_TPFLAGS_HAVE_GC" 并提供一个 "tp_traverse" 处理句柄的实现。 如果该
类型的实例是可变的，则还必须提供 "tp_clear" 的实现。

"Py_TPFLAGS_HAVE_GC"
   设置了此标志位的类型的对象必须符合此处记录的规则。为方便起见，下文
   把这些对象称为容器对象。

容器类型的构造函数必须符合两个规则：

1. 该对象的内在必须使用 "PyObject_GC_New" 或 "PyObject_GC_NewVar" 来分
   配。

2. 初始化了所有可能包含其他容器的引用的字段后，它必须调用
   "PyObject_GC_Track()" 。

同样的，对象的释放器必须符合两个类似的规则：

1. 在引用其它容器的字段失效前，必须调用 "PyObject_GC_UnTrack()" 。

2. 必须使用 "PyObject_GC_Del()" 释放对象的内存。

   警告:

     如果一个类型添加了 Py_TPFLAGS_HAVE_GC，则它 *必须* 实现至少一个
     "tp_traverse" 句柄或显式地使用来自其一个或多个子类的句柄。当调用
     "PyType_Ready()" 或者某些间接调用该函数的 API 如
     "PyType_FromSpecWithBases()" 或 "PyType_FromSpec()" 时解释器将自
     动填充 "tp_flags", "tp_traverse" 和 "tp_clear" 字段，如果该类型是
     继承自实现了垃圾回收器协议的类并且该子类 *没有* 包括
     "Py_TPFLAGS_HAVE_GC" 旗标的话。

PyObject_GC_New(TYPE, typeobj)

   类似于 "PyObject_New" 但专用于设置了 "Py_TPFLAGS_HAVE_GC" 旗标的容
   器对象。

PyObject_GC_NewVar(TYPE, typeobj, size)

   与 "PyObject_NewVar" 类似但专用于设置了 "Py_TPFLAGS_HAVE_GC" 旗标的
   容器对象。

PyObject *PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size)

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

   与 "PyObject_GC_New" 类似但会在对象的末尾分配 *extra_size* 个字节（
   在 "tp_basicsize" 偏移量处）。 除 "Python 对象标头" 外，分配的内存
   将初始化为零。

   附加数据将与对象一起被释放，但在其他情况下则不会由 Python 来管理。

   警告:

     此函数被标记为非稳定的因为在实例之后保留附加数据的机制尚未确定。
     要分配可变数量的字段，推荐改用 "PyVarObject" 和 "tp_itemsize"。

   3.12 新版功能.

TYPE *PyObject_GC_Resize(TYPE, PyVarObject *op, Py_ssize_t newsize)

   重新调整 "PyObject_NewVar" 所分配对象的大小。 返回调整大小后的对象
   或在失败时返回 "NULL"。 *op* 必须尚未被垃圾回收器追踪。

void PyObject_GC_Track(PyObject *op)
    * Part of the Stable ABI.*

   把对象 *op* 加入到垃圾回收器跟踪的容器对象中。对象在被回收器跟踪时
   必须保持有效的，因为回收器可能在任何时候开始运行。在 "tp_traverse"
   处理前的所有字段变为有效后，必须调用此函数，通常在靠近构造函数末尾
   的位置。

int PyObject_IS_GC(PyObject *obj)

   如果对象实现了垃圾回收器协议则返回非零值，否则返回 0。

   如果此函数返回 0 则对象无法被垃圾回收器追踪。

int PyObject_GC_IsTracked(PyObject *op)
    * Part of the Stable ABI since version 3.9.*

   如果 *op* 对象的类型实现了 GC 协议且 *op* 目前正被垃圾回收器追踪则
   返回 1， 否则返回 0。

   这类似于 Python 函数 "gc.is_tracked()"。

   3.9 新版功能.

int PyObject_GC_IsFinalized(PyObject *op)
    * Part of the Stable ABI since version 3.9.*

   如果 *op* 对象的类型实现了 GC 协议且 *op* 已经被垃圾回收器终结则返
   回 1， 否则返回 0。

   这类似于 Python 函数 "gc.is_finalized()"。

   3.9 新版功能.

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

   使用 "PyObject_GC_New" 或 "PyObject_GC_NewVar" 释放分配给对象的内存
   。

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

   从回收器跟踪的容器对象集合中移除 *op* 对象。 请注意可以在此对象上再
   次调用 "PyObject_GC_Track()" 以将其加回到被跟踪对象集合。 释放器
   ("tp_dealloc" 句柄) 应当在 "tp_traverse" 句柄所使用的任何字段失效之
   前为对象调用此函数。

在 3.8 版更改: "_PyObject_GC_TRACK()" 和 "_PyObject_GC_UNTRACK()" 宏已
从公有 C API 中删除。

"tp_traverse" 处理接收以下类型的函数形参。

typedef int (*visitproc)(PyObject *object, void *arg)
    * Part of the Stable ABI.*

   传给 "tp_traverse" 处理的访问函数的类型。*object* 是容器中需要被遍
   历的一个对象，第三个形参对应于 "tp_traverse" 处理的 *arg* 。Python
   核心使用多个访问者函数实现循环引用的垃圾检测，不需要用户自行实现访
   问者函数。

"tp_traverse" 处理必须是以下类型：

typedef int (*traverseproc)(PyObject *self, visitproc visit, void *arg)
    * Part of the Stable ABI.*

   用于容器对象的遍历函数。 它的实现必须对 *self* 所直接包含的每个对象
   调用 *visit* 函数，*visit* 的形参为所包含对象和传给处理程序的 *arg*
   值。 *visit* 函数调用不可附带 "NULL" 对象作为参数。 如果 *visit* 返
   回非零值，则该值应当被立即返回。

为了简化 "tp_traverse" 处理的实现，Python提供了一个 "Py_VISIT()" 宏。
若要使用这个宏，必须把 "tp_traverse" 的参数命名为 *visit* 和 *arg* 。

void Py_VISIT(PyObject *o)

   如果 *o* 不为 "NULL"，则调用 *visit* 回调函数，附带参数 *o* 和
   *arg*。 如果 *visit* 返回一个非零值，则返回该值。 使用此宏之后，
   "tp_traverse" 处理程序的形式如下:

      static int
      my_traverse(Noddy *self, visitproc visit, void *arg)
      {
          Py_VISIT(self->foo);
          Py_VISIT(self->bar);
          return 0;
      }

"tp_clear" 处理程序必须为 "inquiry" 类型，如果对象不可变则为 "NULL"。

typedef int (*inquiry)(PyObject *self)
    * Part of the Stable ABI.*

   丢弃产生循环引用的引用。不可变对象不需要声明此方法，因为他们不可能
   直接产生循环引用。需要注意的是，对象在调用此方法后必须仍是有效的（
   不能对引用只调用 "Py_DECREF()" 方法）。当垃圾回收器检测到该对象在循
   环引用中时，此方法会被调用。


控制垃圾回收器状态
==================

这个 C-API 提供了以下函数用于控制垃圾回收的运行。

Py_ssize_t PyGC_Collect(void)
    * Part of the Stable ABI.*

   执行完全的垃圾回收，如果垃圾回收器已启用的话。 （请注意
   "gc.collect()" 会无条件地执行它。）

   返回已回收的 + 无法回收的不可获取对象的数量。 如果垃圾回收器被禁用
   或已在执行回收，则立即返回 "0"。 在垃圾回收期间发生的错误会被传给
   "sys.unraisablehook"。 此函数不会引发异常。

int PyGC_Enable(void)
    * Part of the Stable ABI since version 3.10.*

   启用垃圾回收器：类似于 "gc.enable()"。 返回之前的状态，0 为禁用而 1
   为启用。

   3.10 新版功能.

int PyGC_Disable(void)
    * Part of the Stable ABI since version 3.10.*

   禁用垃圾回收器：类似于 "gc.disable()"。 返回之前的状态，0 为禁用而
   1 为启用。

   3.10 新版功能.

int PyGC_IsEnabled(void)
    * Part of the Stable ABI since version 3.10.*

   查询垃圾回收器的状态：类似于 "gc.isenabled()"。 返回当前的状态，0
   为禁用而 1 为启用。

   3.10 新版功能.


查询垃圾回收器状态
==================

该 C-API 提供了以下接口用于查询有关垃圾回收器的信息。

void PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg)

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

   在全部活动的支持 GC 的对象上运行所提供的 *callback*。 *arg* 会被传
   递给所有 *callback* 的发起调用。

   警告:

     如果新对象被回调（取消）分配后再被访问其行为是未定义的。垃圾回收
     在运行期间被禁用。 在回调中显式地运行回收可能导致未定义的行为，例
     如多次访问同一对象或完全不访问。

   3.12 新版功能.

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

   要传给 "PyUnstable_GC_VisitObjects()" 的访问者函数的类型。 *arg* 与
   传给 "PyUnstable_GC_VisitObjects" 的 *arg* 相同。 返回 "0" 以继续迭
   代，返回 "1" 以停止迭代。 其他返回值目前被保留因此返回任何其他值的
   行为都是未定义的。

   3.12 新版功能.
