循環参照ガベージコレクションをサポートする¶
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_traversehandler or explicitly use one from its subclass or subclasses.PyType_Ready()、またはPyType_FromSpecWithBases()やPyType_FromSpec()など間接的にこの関数を呼び出す API を使った際、 ガベージコレクタのプロトコルを実装するクラスを継承しており、派生クラスにPy_TPFLAGS_HAVE_GCフラグが含まれて いない 場合は、 インタープリタがtp_flags、tp_traverse、tp_clearフィールドを自動的に設定します。
-
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)¶
- これは Unstable APIです。マイナーリリースで予告なく変更されることがあります。
PyObject_GC_Newと同様ですが、オブジェクトの末尾 (オフセットtp_basicsize) に extra_size バイトを割り当てます。 割り当てたメモリはPython オブジェクトのヘッダーを除いてゼロで初期化されます。追加データはオブジェクトとともに解放されますが、それ以外の管理は Python では行いません。
警告
インスタンスの後ろに追加データを確保する最終的な仕組みが未定のため、この関数は不安定とされています。 可変個数のフィールドを割り当てるには、代わりに
PyVarObjectとtp_itemsizeを使うことが推奨されます。Added in version 3.12.
-
PyObject_GC_Resize(TYPE, op, newsize)¶
Resize an object allocated by
PyObject_NewVar. Returns the resized object of typeTYPE*(refers to any C type) orNULLon failure.op の型は PyVarObject* でなければならず、まだコレクタの追跡対象になっていてはいけません。 newsize の型は
Py_ssize_tでなければなりません。
-
void PyObject_GC_Track(PyObject *op)¶
- 次に属します: Stable ABI.
オブジェクト op を、コレクタが追跡するコンテナオブジェクトの集合に追加します。 コレクタは予期しないタイミングで実行される可能性があるため、追跡中のオブジェクトは有効な状態でなければなりません。
tp_traverseハンドラがたどるすべてのフィールドが有効になった時点で、通常はコンストラクタの終わり近くで呼び出してください。
-
int PyObject_IS_GC(PyObject *obj)¶
オブジェクトがガベージコレクタのプロトコルを実装している場合はゼロ以外、そうでなければ 0 を返します。
この関数が 0 を返す場合、そのオブジェクトをガベージコレクタの追跡対象にはできません。
-
int PyObject_GC_IsTracked(PyObject *op)¶
- 次に属します: Stable ABI (バージョン 3.9 より).
op の型が GC プロトコルを実装しており、op が現在ガベージコレクタに追跡されている場合は 1 を、それ以外の場合は 0 を返します。
Python の
gc.is_tracked()関数に相当します。Added in version 3.9.
-
int PyObject_GC_IsFinalized(PyObject *op)¶
- 次に属します: Stable ABI (バージョン 3.9 より).
op の型が GC プロトコルを実装しており、op がガベージコレクタによってすでにファイナライズされている場合は 1 を、それ以外の場合は 0 を返します。
Python の
gc.is_finalized()関数に相当します。Added in version 3.9.
-
void PyObject_GC_Del(void *op)¶
- 次に属します: Stable ABI.
PyObject_GC_NewまたはPyObject_GC_NewVarでオブジェクトに割り当てたメモリを解放します。
-
void PyObject_GC_UnTrack(void *op)¶
- 次に属します: 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)¶
- 次に属します: 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 が非ゼロの値を返す場合、エラーが発生し、戻り値をそのまま返すようにしなければなりません。The traversal function must not have any side effects. Implementations may not modify the reference counts of any Python objects nor create or destroy any Python objects.
tp_traverse ハンドラを簡潔に書くために、 Py_VISIT() マクロが提供されています。このマクロを使うためには、 tp_traverse の実装関数の引数は、一文字も違わず visit と arg でなければなりません:
-
Py_VISIT(o)¶
If the PyObject* o is not
NULL, call the visit callback, with arguments o and arg. If visit returns a non-zero value, then return it. Using this macro,tp_traversehandlers look like: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()を呼ぶだけにしないでください)。ガベージコレクタは、オブジェクトが循環参照を形成していることを検出した際にこのメソッドを呼び出します。
ガベージコレクタの状態を制御する¶
C API は、ガベージコレクションの実行を制御するために次の関数を提供します。
-
Py_ssize_t PyGC_Collect(void)¶
- 次に属します: Stable ABI.
ガベージコレクタが有効な場合に、完全なガベージコレクションを実行します (
gc.collect()は無条件に実行する点に注意してください)。回収したオブジェクト数と、到達不能なのに回収できないオブジェクト数の合計を返します。 ガベージコレクタが無効か、すでに回収を実行している場合は、直ちに
0を返します。 ガベージコレクション中のエラーはsys.unraisablehookに渡されます。 この関数は例外を送出しません。
-
int PyGC_Enable(void)¶
- 次に属します: Stable ABI (バージョン 3.10 より).
ガベージコレクタを有効にします。
gc.enable()に相当します。 以前の状態を返し、無効だった場合は 0、有効だった場合は 1 です。Added in version 3.10.
-
int PyGC_Disable(void)¶
- 次に属します: Stable ABI (バージョン 3.10 より).
ガベージコレクタを無効にします。
gc.disable()に相当します。 以前の状態を返し、無効だった場合は 0、有効だった場合は 1 です。Added in version 3.10.
-
int PyGC_IsEnabled(void)¶
- 次に属します: Stable ABI (バージョン 3.10 より).
ガベージコレクタの状態を問い合わせます。
gc.isenabled()に相当します。 現在の状態を返し、無効の場合は 0、有効の場合は 1 です。Added in version 3.10.
ガベージコレクタの状態を問い合わせる¶
C API は、ガベージコレクタの情報を問い合わせるために次のインターフェースを提供します。
-
void PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg)¶
- これは Unstable APIです。マイナーリリースで予告なく変更されることがあります。
生存しているすべての GC 対応オブジェクトに対して、指定された callback を実行します。 callback を呼び出すたびに arg をそのまま渡します。
警告
コールバックがオブジェクトを割り当てたり解放したりした場合、それらのオブジェクトが巡回されるかどうかは未定義です。
処理中はガベージコレクションが無効になります。 コールバック内で明示的にコレクションを実行すると、同じオブジェクトを複数回巡回したり、まったく巡回しなかったりするなど、未定義の動作を引き起こす可能性があります。
Added in version 3.12.
-
typedef int (*gcvisitobjects_t)(PyObject *object, void *arg)¶
PyUnstable_GC_VisitObjects()に渡すビジター関数の型です。 arg はPyUnstable_GC_VisitObjectsに渡された arg と同じです。 反復処理を続けるには1、停止するには0を返してください。 その他の戻り値は現在予約されており、これら以外の値を返した場合の動作は未定義です。Added in version 3.12.