Поддержка циклической сборки мусора¶
Поддержка Python для обнаружения и сбора мусора, включающего циклические ссылки, требует поддержки со стороны типов объектов, которые являются «контейнерами» для других объектов, которые также могут быть контейнерами. Типы, которые не хранят ссылки на другие объекты или хранят только ссылки на атомарные типы (такие как числа или строки), не нуждаются в явной поддержке сборки мусора.
Чтобы создать контейнерный тип, поле tp_flags
объекта типа должно включать Py_TPFLAGS_HAVE_GC
и обеспечивать реализацию обработчика tp_traverse
. Если экземпляры типа являются изменяемыми, необходимо также предоставить реализацию tp_clear
.
-
Py_TPFLAGS_HAVE_GC
Объекты, имеющие тип с установленным этим флагом, должны соответствовать правилам, задокументированным здесь. Для удобства эти объекты будут называться объектами-контейнерами.
Конструкторы для типов контейнеров должны соответствовать двум правилам:
Память для объекта должна быть выделена с помощью
PyObject_GC_New()
илиPyObject_GC_NewVar()
.После инициализации всех полей, которые могут содержать ссылки на другие контейнеры, он должен вызвать
PyObject_GC_Track()
.
Аналогично, деаллокатор для объекта должен соответствовать аналогичной паре правил:
Прежде чем поля, ссылающиеся на другие контейнеры, будут аннулированы, необходимо вызвать
PyObject_GC_UnTrack()
.Память объекта должна быть деаллоцирована с помощью
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
.
-
TYPE *
PyObject_GC_New
(TYPE, PyTypeObject *type)¶ Аналог
PyObject_New()
, но для объектов-контейнеров с установленным флагомPy_TPFLAGS_HAVE_GC
.
-
TYPE *
PyObject_GC_NewVar
(TYPE, PyTypeObject *type, Py_ssize_t size)¶ Аналог
PyObject_NewVar()
, но для объектов-контейнеров с установленным флагомPy_TPFLAGS_HAVE_GC
.
-
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.
Возвращает 1, если тип объекта op реализует протокол GC и op в настоящее время отслеживается сборщиком мусора, и 0 в противном случае.
Это аналогично функции Python
gc.is_tracked()
.Добавлено в версии 3.9.
-
int
PyObject_GC_IsFinalized
(PyObject *op)¶ - Part of the Stable ABI since version 3.9.
Возвращает 1, если тип объекта op реализует протокол GC и op уже был финализирован сборщиком мусора, и 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()
были удалены из общедоступного API языка C.
Обработчик 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.
Функция обхода для объекта-контейнера. Реализации должны вызывать функцию visit для каждого объекта, непосредственно содержащегося в self, при этом параметрами visit являются содержащийся объект и значение arg, переданное обработчику. Функция visit не должна вызываться с аргументом объекта
NULL
. Если visit возвращает ненулевое значение, оно должно быть возвращено немедленно.
Для упрощения написания обработчиков tp_traverse
предусмотрен макрос 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.