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

Поддержка 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.

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.

Вернуться на верх