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

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

コンテナ型を作るには、型オブジェクトの "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()" を呼び出さなければなりません。

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" の対象となる全てのフィールドが正しい状態になってすぐ
   に、たいていはコンストラクタの末尾付近で、呼び出すべきです。

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

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

2. オブジェクトのメモリは "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_traverse" ハンドラの対象となるフィールドが正しくない状態になる
   前に、デアロケータ ("tp_dealloc" ハンドラ) はオブジェクトに対して、
   この関数を呼び出すべきです。

バージョン 3.8 で変更: "_PyObject_GC_TRACK()" マクロと
"_PyObject_GC_UNTRACK()" マクロは公開 C API から外されました。

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

int (*visitproc)(PyObject *object, void *arg)

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

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

int (*traverseproc)(PyObject *self, visitproc visit, void *arg)

   コンテナオブジェクトのためのトラバーサル関数 (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" でなければなりません。

int (*inquiry)(PyObject *self)

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