Поддержка циклической сборки мусора¶
Поддержка Python для обнаружения и сбора мусора, который включает циклические ссылки, требует поддержки со стороны типов объектов, которые являются «контейнерами» для других объектов, которые также могут быть контейнерами. Типы, которые не хранят ссылки на другие объекты или которые хранят ссылки только на атомарные типы (такие как числа или строки), не нуждаются в какой-либо явной поддержке сборки мусора.
Чтобы создать тип контейнера, поле tp_flags
объекта type должно содержать 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
, :c<<поля :member:`~PyTypeObject.tp_traverse` <4>>> и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_GC_Resize(TYPE, op, newsize)¶
Измените размер объекта, выделенного с помощью
PyObject_NewVar
. В случае сбоя возвращает объект измененного размера типаTYPE*
(относится к любому типу C) илиNULL
.op должен иметь тип PyVarObject* и пока не должен отслеживаться сборщиком. newsize должен иметь тип
Py_ssize_t
.
-
void PyObject_GC_Track(PyObject *op)¶
- Part of the Стабильный ABI.
Добавляет объект op в набор объектов-контейнеров, отслеживаемых сборщиком. Сборщик может запускаться в непредвиденные моменты, поэтому объекты должны быть действительными во время отслеживания. Это должно быть вызвано, как только все поля, за которыми следует обработчик
tp_traverse
, станут действительными, обычно ближе к концу конструктора.
-
int PyObject_IS_GC(PyObject *obj)¶
Возвращает ненулевое значение, если объект реализует протокол сборщика мусора, в противном случае возвращает 0.
Сборщик мусора не может отследить объект, если эта функция возвращает 0.
-
int PyObject_GC_IsTracked(PyObject *op)¶
- Part of the Стабильный ABI since version 3.9.
Возвращает 1, если тип объекта op реализует протокол сбора мусора и op в данный момент отслеживается сборщиком мусора, и 0 в противном случае.
Это аналогично функции Python
gc.is_tracked()
.Добавлено в версии 3.9.
-
int PyObject_GC_IsFinalized(PyObject *op)¶
- Part of the Стабильный ABI since version 3.9.
Возвращает 1, если тип объекта op реализует протокол сбора мусора, а op уже был завершен сборщиком мусора, и 0 в противном случае.
Это аналогично функции Python
gc.is_finalized()
.Добавлено в версии 3.9.
-
void PyObject_GC_Del(void *op)¶
- Part of the Стабильный ABI.
Освобождает память, выделенную объекту, используя
PyObject_GC_New
илиPyObject_GC_NewVar
.
-
void PyObject_GC_UnTrack(void *op)¶
- Part of the Стабильный ABI.
Удалите объект op из набора объектов-контейнеров, отслеживаемых сборщиком. Обратите внимание, что для этого объекта можно снова вызвать
PyObject_GC_Track()
, чтобы добавить его обратно в набор отслеживаемых объектов. Средство освобождения (обработчик:c:member:~PyTypeObject.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 Стабильный ABI.
Тип функции visitor передается обработчику
tp_traverse
. Функция должна вызываться с объектом для обхода в виде object и третьим параметром для обработчикаtp_traverse
в виде arg. Ядро Python использует несколько функций visitor для реализации циклического обнаружения мусора; не ожидается, что пользователям потребуется писать свои собственные функции visitor.
Обработчик tp_traverse
должен иметь следующий тип:
-
typedef int (*traverseproc)(PyObject *self, visitproc visit, void *arg)¶
- Part of the Стабильный ABI.
Функция обхода для объекта-контейнера. Реализации должны вызывать функцию visit для каждого объекта, непосредственно содержащегося в self, при этом параметрами для visit являются содержащийся объект, а значение arg передается обработчику. Функция visit не должна вызываться с аргументом
NULL
object. Если 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 Стабильный ABI.
Удалите ссылки, которые могли создать ссылочные циклы. Неизменяемые объекты не обязаны определять этот метод, поскольку они никогда не смогут напрямую создавать ссылочные циклы. Обратите внимание, что объект должен оставаться действительным после вызова этого метода (не вызывайте просто
Py_DECREF()
для ссылки). Сборщик вызовет этот метод, если обнаружит, что этот объект вовлечен в ссылочный цикл.
Управление состоянием сборщика мусора¶
C-API предоставляет следующие функции для управления выполнением сборки мусора.
-
Py_ssize_t PyGC_Collect(void)¶
- Part of the Стабильный ABI.
Выполните полную сборку мусора, если включен сборщик мусора. (Обратите внимание, что
gc.collect()
запускает его без каких-либо условий.)Возвращает количество собранных + недоступных объектов, которые не могут быть собраны. Если сборщик мусора отключен или уже начал сбор, немедленно возвращает
0
. Ошибки во время сборки мусора передаются вsys.unraisablehook
. Эта функция не вызывает исключений.
-
int PyGC_Enable(void)¶
- Part of the Стабильный ABI since version 3.10.
Включите сборщик мусора: аналогично
gc.enable()
. Возвращает предыдущее состояние, 0 для отключенного и 1 для включенного.Добавлено в версии 3.10.
-
int PyGC_Disable(void)¶
- Part of the Стабильный ABI since version 3.10.
Отключите сборщик мусора: аналогично
gc.disable()
. Возвращает предыдущее состояние, 0 для отключенного и 1 для включенного.Добавлено в версии 3.10.
-
int PyGC_IsEnabled(void)¶
- Part of the Стабильный ABI since version 3.10.
Запросите состояние сборщика мусора: аналогично
gc.isenabled()
. Возвращает текущее состояние, 0 для отключенного и 1 для включенного.Добавлено в версии 3.10.