サイクリックガベージコレクションのサポート
循環参照を含むガベージの検出と収集に対するPythonのサポートには、コンテナーである可能性のある他のオブジェクトの「コンテナー」であるオブジェクトタイプからのサポートが必要です。 他のオブジェクトへの参照を格納しないタイプ、またはアトミックタイプ(数値や文字列など)への参照のみを格納するタイプは、ガベージコレクションを明示的にサポートする必要はありません。
コンテナタイプを作成するには、タイプオブジェクトの tp_flags フィールドに Py_TPFLAGS_HAVE_GC が含まれ、 tp_traverse ハンドラーの実装を提供する必要があります。 タイプのインスタンスが可変である場合は、 tp_clear 実装も提供する必要があります。
- Py_TPFLAGS_HAVE_GC
- このフラグが設定されたタイプのオブジェクトは、ここに記載されているルールに準拠している必要があります。 便宜上、これらのオブジェクトはコンテナオブジェクトと呼ばれます。
コンテナタイプのコンストラクタは、次の2つのルールに準拠する必要があります。
オブジェクトのメモリは、 PyObject_GC_New()または PyObject_GC_NewVar()を使用して割り当てる必要があります。
他のコンテナへの参照を含む可能性のあるすべてのフィールドが初期化されたら、 PyObject_GC_Track()を呼び出す必要があります。
警告
タイプがPy_TPFLAGS_HAVE_GCを追加する場合、そのタイプは少なくとも tp_traverse ハンドラーを実装するか、そのサブクラスから1つまたは複数のサブクラスを明示的に使用する必要があります。
PyType_Ready()、または PyType_FromSpecWithBases()や PyType_FromSpec()などの間接的に呼び出すAPIの一部を呼び出すと、インタープリターは自動的に 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)
- オブジェクト op を、コレクターによって追跡されるコンテナーオブジェクトのセットに追加します。 コレクターは予期しないときに実行される可能性があるため、追跡中はオブジェクトが有効である必要があります。 これは、 tp_traverse ハンドラーが続くすべてのフィールドが有効になったら、通常はコンストラクターの終わり近くで呼び出す必要があります。
- int PyObject_IS_GC(PyObject *obj)
オブジェクトがガベージコレクタプロトコルを実装している場合はゼロ以外を返し、それ以外の場合は0を返します。
この関数が0を返す場合、オブジェクトはガベージコレクターによって追跡できません。
- int PyObject_GC_IsTracked(PyObject *op)
op のオブジェクトタイプがGCプロトコルを実装し、 op が現在ガベージコレクターによって追跡されている場合は1を返し、それ以外の場合は0を返します。
これは、Python関数 gc.is_tracked()に類似しています。
バージョン3.9の新機能。
- int PyObject_GC_IsFinalized(PyObject *op)
op のオブジェクトタイプがGCプロトコルを実装し、 op がガベージコレクターによってすでにファイナライズされている場合は1を返し、それ以外の場合は0を返します。
これは、Python関数 gc.is_finalized()に類似しています。
バージョン3.9の新機能。
同様に、オブジェクトのデアロケーターは、同様のルールのペアに準拠する必要があります。
- 他のコンテナを参照するフィールドを無効にする前に、 PyObject_GC_UnTrack()を呼び出す必要があります。
- オブジェクトのメモリは、 PyObject_GC_Del()を使用して割り当てを解除する必要があります。
- void PyObject_GC_Del(void *op)
- PyObject_GC_New()または PyObject_GC_NewVar()を使用してオブジェクトに割り当てられたメモリを解放します。
- void PyObject_GC_UnTrack(void *op)
- コレクターによって追跡されるコンテナーオブジェクトのセットからオブジェクト op を削除します。 PyObject_GC_Track()をこのオブジェクトで再度呼び出して、追跡対象のオブジェクトのセットに追加し直すことができることに注意してください。 デアロケーター( tp_dealloc ハンドラー)は、 tp_traverse ハンドラーによって使用されるフィールドが無効になる前に、オブジェクトに対してこれを呼び出す必要があります。
バージョン3.8での変更: _PyObject_GC_TRACK()
および_PyObject_GC_UNTRACK()
マクロはパブリックCAPIから削除されました。
tp_traverse ハンドラーは、次のタイプの関数パラメーターを受け入れます。
- typedef int (*visitproc)(PyObject *object, void *arg)
- tp_traverse ハンドラーに渡されるビジター関数のタイプ。 この関数は、 object としてトラバースするオブジェクトと、 arg として tp_traverse ハンドラーへの3番目のパラメーターを指定して呼び出す必要があります。 Pythonコアは、いくつかのビジター関数を使用して、周期的なガベージ検出を実装します。 ユーザーが独自のビジター関数を作成する必要があるとは思われません。
tp_traverse ハンドラーは、次のタイプである必要があります。
- コンテナオブジェクトのトラバーサル関数。 実装は、 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 タイプであるか、オブジェクトが不変の場合はNULL
である必要があります。
- typedef int (*inquiry)(PyObject *self)
- 参照サイクルを作成した可能性のある参照を削除します。 不変オブジェクトは、参照サイクルを直接作成できないため、このメソッドを定義する必要はありません。 このメソッドを呼び出した後も、オブジェクトは引き続き有効である必要があることに注意してください(参照で Py_DECREF()を呼び出すだけではありません)。 コレクターは、このオブジェクトが参照サイクルに関与していることを検出すると、このメソッドを呼び出します。
ガベージコレクターの状態の制御
C-APIは、ガベージコレクションの実行を制御するために次の関数を提供します。
- Py_ssize_t PyGC_Collect(void)
ガベージコレクタが有効になっている場合は、完全なガベージコレクションを実行します。 ( gc.collect()は無条件に実行することに注意してください。)
収集された+収集できない到達不能オブジェクトの数を返します。 ガベージコレクタが無効になっている場合、またはすでに収集している場合は、すぐに
0
を返します。 ガベージコレクション中のエラーは sys.unraisablehook に渡されます。 この関数は例外を発生させません。
- int PyGC_Enable(void)
ガベージコレクターを有効にします: gc.enable()と同様です。 以前の状態を返します。0は無効、1は有効です。
バージョン3.10の新機能。
- int PyGC_Disable(void)
ガベージコレクターを無効にします: gc.disable()と同様です。 以前の状態を返します。0は無効、1は有効です。
バージョン3.10の新機能。
- int PyGC_IsEnabled(void)
ガベージコレクターの状態を照会します: gc.isenabled()と同様です。 現在の状態を返します。0は無効、1は有効です。
バージョン3.10の新機能。