Поддержка циклического сборщика мусора
Поддержка 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.
-
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) -
Входит в стабильный ABI.
Добавляет объект op в набор объектов-контейнеров, отслеживаемых сборщиком. Сборщик может запускаться в неожиданные моменты, поэтому отслеживаемые объекты должны быть корректными. Этот вызов следует выполнять после того, как станут корректными все поля, обрабатываемые обработчиком
tp_traverse, обычно ближе к концу конструктора.
-
int PyObject_IS_GC(PyObject *obj) -
Возвращает ненулевое значение, если объект реализует протокол сборщика мусора, в противном случае возвращает 0.
Если эта функция возвращает 0, сборщик мусора не может отслеживать объект.
-
int PyObject_GC_IsTracked(PyObject *op) -
Входит в стабильный ABI начиная с версии 3.9.
Возвращает 1, если тип объекта op реализует протокол GC и op в данный момент отслеживается сборщиком мусора, и 0 в противном случае.
Аналогична функции Python
gc.is_tracked().Добавлено в версии 3.9.
-
int PyObject_GC_IsFinalized(PyObject *op) -
Входит в стабильный ABI начиная с версии 3.9.
Возвращает 1, если тип объекта op реализует протокол GC и объект op уже был финализирован сборщиком мусора, и 0 в противном случае.
Аналогична функции Python
gc.is_finalized().Добавлено в версии 3.9.
-
void PyObject_GC_Del(void *op) -
Входит в стабильный ABI.
Освобождает память объекта, выделенную с помощью
PyObject_GC_NewилиPyObject_GC_NewVar.
-
void PyObject_GC_UnTrack(void *op) -
Входит в стабильный 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) -
Входит в стабильный ABI.
Тип функции-посетителя, передаваемой обработчику
tp_traverse. Функцию следует вызывать, передав объект для обхода в качестве object, а третий параметр обработчикаtp_traverse— в качестве arg. Ядро Python использует несколько функций-посетителей для реализации обнаружения циклического мусора; предполагается, что пользователям не потребуется писать собственные функции-посетители.
Обработчик tp_traverse должен иметь следующий тип:
-
typedef int (*traverseproc)(PyObject *self, visitproc visit, void *arg) -
Входит в стабильный 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) -
Входит в стабильный ABI.
Удаляет ссылки, которые могли создать циклы ссылок. Неизменяемым объектам не нужно определять этот метод, поскольку они не могут напрямую создавать циклы ссылок. Обратите внимание: после вызова этого метода объект должен оставаться корректным (не следует просто вызывать
Py_DECREF()для ссылки). Сборщик вызовет этот метод, если обнаружит, что объект участвует в цикле ссылок.
Управление состоянием сборщика мусора
C API предоставляет следующие функции для управления запусками сборщика мусора.
-
Py_ssize_t PyGC_Collect(void) -
Входит в стабильный ABI.
Выполняет полную сборку мусора, если сборщик мусора включён. (Обратите внимание:
gc.collect()выполняет её безусловно.)Возвращает количество собранных объектов плюс количество недостижимых объектов, которые не удалось собрать. Если сборщик мусора отключён или уже выполняет сборку, немедленно возвращает
0. Ошибки во время сборки мусора передаются вsys.unraisablehook. Эта функция не вызывает исключений.
-
int PyGC_Enable(void) -
Входит в стабильный ABI начиная с версии 3.10.
Включает сборщик мусора: аналогична
gc.enable(). Возвращает предыдущее состояние: 0 — выключен, 1 — включён.Добавлено в версии 3.10.
-
int PyGC_Disable(void) -
Входит в стабильный ABI начиная с версии 3.10.
Отключает сборщик мусора: аналогична
gc.disable(). Возвращает предыдущее состояние: 0 — выключен, 1 — включён.Добавлено в версии 3.10.
-
int PyGC_IsEnabled(void) -
Входит в стабильный ABI начиная с версии 3.10.
Проверяет состояние сборщика мусора: аналогична
gc.isenabled(). Возвращает текущее состояние: 0 — выключен, 1 — включён.Добавлено в версии 3.10.
© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/c-api/gcsupport.html