Поддержка циклической сборки мусора

Поддержка 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)
Это Нестабильный API. Она может меняться без предупреждения в небольших выпусках.

Аналогично PyObject_GC_New, но выделяет extra_size байт в конце объекта (по смещению tp_basicsize). Выделенная память инициализируется нулями, за исключением Python object header.

Дополнительные данные будут удалены вместе с объектом, но в остальном они не управляются Python.

Предупреждение

Функция помечена как нестабильная, поскольку окончательный механизм резервирования дополнительных данных после экземпляра еще не определен. Для выделения переменного количества полей лучше использовать PyVarObject и tp_itemsize.

Added in version 3.12.

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().

Added in version 3.9.

int PyObject_GC_IsFinalized(PyObject *op)
Часть Стабильный ABI с версии 3.9.

Возвращает 1, если тип объекта op реализует протокол GC и op уже был финализирован сборщиком мусора, и 0 в противном случае.

Это аналогично функции Python gc.is_finalized().

Added in version 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() может быть вызвана снова для этого объекта, чтобы добавить его обратно в набор отслеживаемых объектов. Деаллокатор (обработчик:c:member:~PyTypeObject.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 - включено.

Added in version 3.10.

int PyGC_Disable(void)
Часть Стабильный ABI с версии 3.10.

Отключить сборщик мусора: аналогично gc.disable(). Возвращает предыдущее состояние, 0 для отключенного и 1 для включенного.

Added in version 3.10.

int PyGC_IsEnabled(void)
Часть Стабильный ABI с версии 3.10.

Запрос состояния сборщика мусора: аналогично gc.isenabled(). Возвращает текущее состояние, 0 - выключено, 1 - включено.

Added in version 3.10.

Запрос состояния сборщика мусора

C-API предоставляет следующий интерфейс для запроса информации о сборщике мусора.

void PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg)
Это Нестабильный API. Она может меняться без предупреждения в небольших выпусках.

Запускает предоставленный callback на всех живых объектах, способных к GC. arg передается во все вызовы callback.

Предупреждение

Если новые объекты (де)выделены обратным вызовом, то не определено, будут ли они посещены.

Во время работы сборка мусора отключена. Явный запуск сборки в обратном вызове может привести к неопределенному поведению, например, посещению одних и тех же объектов несколько раз или не посещению вообще.

Added in version 3.12.

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

Тип функции-посетителя, передаваемой в PyUnstable_GC_VisitObjects(). arg - то же самое, что и arg, переданный в PyUnstable_GC_VisitObjects. Верните 0, чтобы продолжить итерацию, верните 1, чтобы остановить итерацию. Другие возвращаемые значения пока зарезервированы, поэтому поведение при возврате чего-либо еще не определено.

Added in version 3.12.