循環参照ガベージコレクションをサポートする

Python が循環参照を含むガベージの検出とコレクションをサポートするには、他のオブジェクトに対する "コンテナ" (他のオブジェクトには他のコンテナも含みます) となるオブジェクト型によるサポートが必要です。他のオブジェクトに対する参照を記憶しないオブジェクトや、(数値や文字列のような) アトム型 (atomic type) への参照だけを記憶するような型では、ガベージコレクションに際して特別これといったサポートを提供する必要はありません。

To create a container type, the tp_flags field of the type object must include the Py_TPFLAGS_HAVE_GC and provide an implementation of the tp_traverse handler. If instances of the type are mutable, a tp_clear implementation must also be provided.

Py_TPFLAGS_HAVE_GC

このフラグをセットした型のオブジェクトは、この節に述べた規則に適合しなければなりません。簡単のため、このフラグをセットした型のオブジェクトをコンテナオブジェクトと呼びます。

コンテナ型のコンストラクタは以下の二つの規則に適合しなければなりません:

  1. The memory for the object must be allocated using PyObject_GC_New or PyObject_GC_NewVar.

  2. 他のコンテナへの参照が入るかもしれないフィールドが全て初期化されたら、すぐに PyObject_GC_Track() を呼び出さなければなりません。

同様に、オブジェクトのメモリ解放関数も以下の二つの規則に適合しなければなりません:

  1. 他のコンテナを参照しているフィールドを無効化する前に、 PyObject_GC_UnTrack() を呼び出さなければなりません。

  2. オブジェクトのメモリは PyObject_GC_Del() で解放しなければなりません。

    警告

    If a type adds the Py_TPFLAGS_HAVE_GC, then it must implement at least a tp_traverse handler or explicitly use one from its subclass or subclasses.

    When calling PyType_Ready() or some of the APIs that indirectly call it like PyType_FromSpecWithBases() or PyType_FromSpec() the interpreter will automatically populate the tp_flags, tp_traverse and tp_clear fields if the type inherits from a class that implements the garbage collector protocol and the child class does not include the Py_TPFLAGS_HAVE_GC flag.

PyObject_GC_New(TYPE, typeobj)

Analogous to PyObject_New but for container objects with the Py_TPFLAGS_HAVE_GC flag set.

PyObject_GC_NewVar(TYPE, typeobj, size)

Analogous to PyObject_NewVar but for container objects with the Py_TPFLAGS_HAVE_GC flag set.

PyObject_GC_Resize(TYPE, op, newsize)

Resize an object allocated by PyObject_NewVar. Returns the resized object of type TYPE* (refers to any C type) or NULL on failure.

op must be of type PyVarObject* and must not be tracked by the collector yet. newsize must be of type Py_ssize_t.

void PyObject_GC_Track(PyObject *op)
次に属します: Stable ABI.

オブジェクト op を、コレクタによって追跡されるオブジェクトの集合に追加します。コレクタは何回動くのかは予想できないので、追跡されている間はオブジェクトは正しい状態でいなければなりません。 tp_traverse の対象となる全てのフィールドが正しい状態になってすぐに、たいていはコンストラクタの末尾付近で、呼び出すべきです。

int PyObject_IS_GC(PyObject *obj)

Returns non-zero if the object implements the garbage collector protocol, otherwise returns 0.

The object cannot be tracked by the garbage collector if this function returns 0.

int PyObject_GC_IsTracked(PyObject *op)
次に属します: Stable ABI (バージョン 3.9 より).

Returns 1 if the object type of op implements the GC protocol and op is being currently tracked by the garbage collector and 0 otherwise.

This is analogous to the Python function gc.is_tracked().

バージョン 3.9 で追加.

int PyObject_GC_IsFinalized(PyObject *op)
次に属します: Stable ABI (バージョン 3.9 より).

Returns 1 if the object type of op implements the GC protocol and op has been already finalized by the garbage collector and 0 otherwise.

This is analogous to the Python function gc.is_finalized().

バージョン 3.9 で追加.

void PyObject_GC_Del(void *op)
次に属します: Stable ABI.

Releases memory allocated to an object using PyObject_GC_New or PyObject_GC_NewVar.

void PyObject_GC_UnTrack(void *op)
次に属します: Stable ABI.

オブジェクト op を、コレクタによって追跡されるオブジェクトの集合から除去します。このオブジェクトに対して PyObject_GC_Track() を再度呼び出して、追跡されるオブジェクトの集合に戻すことも可能です。 tp_traverse ハンドラの対象となるフィールドが正しくない状態になる前に、デアロケータ (tp_dealloc ハンドラ) はオブジェクトに対して、この関数を呼び出すべきです。

バージョン 3.8 で変更: The _PyObject_GC_TRACK() and _PyObject_GC_UNTRACK() macros have been removed from the public C API.

tp_traverse ハンドラはこの型の関数パラメータを受け取ります:

typedef int (*visitproc)(PyObject *object, void *arg)
次に属します: Stable ABI.

tp_traverse ハンドラに渡されるビジター関数 (visitor function) の型です。この関数は、探索するオブジェクトを object として、 tp_traverse ハンドラの第 3 引数を arg として呼び出します。 Python のコアはいくつかのビジター関数を使って、ゴミとなった循環参照を検出する仕組みを実装します; ユーザが自身のためにビジター関数を書く必要が出てくることはないでしょう。

tp_traverse ハンドラは次の型を持っていなければなりません:

typedef int (*traverseproc)(PyObject *self, visitproc visit, void *arg)
次に属します: Stable ABI.

コンテナオブジェクトのためのトラバーサル関数 (traversal function) です。 実装では、self に直接入っている各オブジェクトに対して visit 関数を呼び出さなければなりません。 このとき、visit へのパラメタはコンテナに入っている各オブジェクトと、このハンドラに渡された arg の値です。 visit 関数は NULL オブジェクトを引数に渡して呼び出してはなりません。 visit が非ゼロの値を返す場合、エラーが発生し、戻り値をそのまま返すようにしなければなりません。

tp_traverse ハンドラを簡潔に書くために、 Py_VISIT() マクロが提供されています。このマクロを使うためには、 tp_traverse の実装関数の引数は、一文字も違わず visitarg でなければなりません:

void Py_VISIT(PyObject *o)

oNULL でなければ、 oarg を引数にして visit コールバックを呼び出します。 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 型であるか、オブジェクトが不変 (immutable) な場合は NULL でなければなりません。

typedef int (*inquiry)(PyObject *self)
次に属します: Stable ABI.

循環参照を形成しているとおぼしき参照群を放棄します。変更不可能なオブジェクトは循環参照を直接形成することが決してないので、この関数を定義する必要はありません。このメソッドを呼び出した後でもオブジェクトは有効なままでなければならないので注意してください (参照に対して Py_DECREF() を呼ぶだけにしないでください)。ガベージコレクタは、オブジェクトが循環参照を形成していることを検出した際にこのメソッドを呼び出します。

Controlling the Garbage Collector State

The C-API provides the following functions for controlling garbage collection runs.

Py_ssize_t PyGC_Collect(void)
次に属します: Stable ABI.

Perform a full garbage collection, if the garbage collector is enabled. (Note that gc.collect() runs it unconditionally.)

Returns the number of collected + unreachable objects which cannot be collected. If the garbage collector is disabled or already collecting, returns 0 immediately. Errors during garbage collection are passed to sys.unraisablehook. This function does not raise exceptions.

int PyGC_Enable(void)
次に属します: Stable ABI (バージョン 3.10 より).

Enable the garbage collector: similar to gc.enable(). Returns the previous state, 0 for disabled and 1 for enabled.

バージョン 3.10 で追加.

int PyGC_Disable(void)
次に属します: Stable ABI (バージョン 3.10 より).

Disable the garbage collector: similar to gc.disable(). Returns the previous state, 0 for disabled and 1 for enabled.

バージョン 3.10 で追加.

int PyGC_IsEnabled(void)
次に属します: Stable ABI (バージョン 3.10 より).

Query the state of the garbage collector: similar to gc.isenabled(). Returns the current state, 0 for disabled and 1 for enabled.

バージョン 3.10 で追加.