循環参照ガベージコレクションをサポートする¶
Python が循環参照を含むガベージの検出とコレクションをサポートするには、他のオブジェクトに対する "コンテナ" (他のオブジェクトには他のコンテナも含みます) となるオブジェクト型によるサポートが必要です。他のオブジェクトに対する参照を記憶しないオブジェクトや、(数値や文字列のような) アトム型 (atomic type) への参照だけを記憶するような型では、ガベージコレクションに際して特別これといったサポートを提供する必要はありません。
コンテナ型を作るには、型オブジェクトの 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()
で解放しなければなりません。警告
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 likePyType_FromSpecWithBases()
orPyType_FromSpec()
the interpreter will automatically populate thetp_flags
,tp_traverse
andtp_clear
fields if the type inherits from a class that implements the garbage collector protocol and the child class does not include thePy_TPFLAGS_HAVE_GC
flag.
-
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)¶ 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)¶ - Part of the Stable ABI since version 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)¶ - Part of the Stable ABI since version 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)¶ - 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_traverse
ハンドラの対象となるフィールドが正しくない状態になる前に、デアロケータ (tp_dealloc
ハンドラ) はオブジェクトに対して、この関数を呼び出すべきです。
バージョン 3.8 で変更: _PyObject_GC_TRACK()
マクロと _PyObject_GC_UNTRACK()
マクロは公開 C API から外されました。
tp_traverse
ハンドラはこの型の関数パラメータを受け取ります:
-
typedef int (*
visitproc
)(PyObject *object, void *arg)¶ - Part of the Stable ABI.
tp_traverse
ハンドラに渡されるビジター関数 (visitor function) の型です。この関数は、探索するオブジェクトを object として、tp_traverse
ハンドラの第 3 引数を arg として呼び出します。 Python のコアはいくつかのビジター関数を使って、ゴミとなった循環参照を検出する仕組みを実装します; ユーザが自身のためにビジター関数を書く必要が出てくることはないでしょう。
tp_traverse
ハンドラは次の型を持っていなければなりません:
-
typedef int (*
traverseproc
)(PyObject *self, visitproc visit, void *arg)¶ - Part of the Stable ABI.
コンテナオブジェクトのためのトラバーサル関数 (traversal function) です。 実装では、self に直接入っている各オブジェクトに対して visit 関数を呼び出さなければなりません。 このとき、visit へのパラメタはコンテナに入っている各オブジェクトと、このハンドラに渡された arg の値です。 visit 関数は
NULL
オブジェクトを引数に渡して呼び出してはなりません。 visit が非ゼロの値を返す場合、エラーが発生し、戻り値をそのまま返すようにしなければなりません。
tp_traverse
ハンドラを簡潔に書くために、 Py_VISIT()
マクロが提供されています。このマクロを使うためには、 tp_traverse
の実装関数の引数は、一文字も違わず visit と arg でなければなりません:
-
void
Py_VISIT
(PyObject *o)¶ o が
NULL
でなければ、 o と arg を引数にして 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)¶ - Part of the 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)¶ - Part of the 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 tosys.unraisablehook
. This function does not raise exceptions.
-
int
PyGC_Enable
(void)¶ - Part of the Stable ABI since version 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)¶ - Part of the Stable ABI since version 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)¶ - Part of the Stable ABI since version 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 で追加.