外部参照ポインタの GC (分散 GC) は,
重み付け参照カウント (WRC = Weighted Reference Counting)
を用いたアルゴリズムを適用する。
この、WRCアルゴリズムを外部参照ポインタGCに適用したものを
特にWEC(Weighted Export Counter)と読んでいる。
このアルゴリズムは、輸出表エントリと外部参照ポインタが正の任意の重み
(WEC)を持ち、
「ある輸出表エントリの重み」と
「そのエントリを指す外部参照ポインタの重みの合計」が
等しくなるように制御するものである。
ある輸出表エントリの重みがゼロならば、
そのエントリを指す外部参照ポインタは存在しない
(そのエントリがゴミになった)ことが保証される。
このWECは「輸出表」(
ページ、第10.2.2章参照)と
exref class、read_hook classのオブジェクトの内部に記録されている。
通常のリファレンスカウントであると、参照側の重みはつねに1として、
参照数を正確に数えることにより参照管理を行うが、WEC(= WRC)方式では、
重みが1にかぎらない。
その結果、参照を他のノードにコピーする際に、参照元と通信を行うなどして
参照数の管理を管理する必要なく、自分の「重み」を他のノードに「分割する」
ことにより参照をコピーすることができ、効率的な分散参照管理が可能となる。
すなわち、 ジェネレータ外部参照ポインタを「分割」して他のノードへ渡す時は、 重みを分割し、一方を他ノードへ渡すポインタに付け、 もう一方はノード内に残す。 これを「分割輸出」と呼ぶ(図10.6 (1))。 重みが分割できない時は「間接輸出」を行う。 これは変数と同じように外部参照ポインタを 輸出表に登録して輸出するものである(図10.7)。 コンシューマ外部参照ポインタはいつも間接輸出を行う。
さて、外部参照ポインタは以下の時に「解放」する。
この処理のために、そのノード内に存在する外部参照を すべて記録している。この記録されている表を「輸入表」と呼ぶ。 この輸入表は、runtime/import_table.c内で定義されている各種関数で メンテナンスされている。GCが終了したときには、scan_imp_table() が呼びだされ、 この輸入表を各オブジェクト毎に嘗めコピーされたかどうかを判断する。
外部参照ポインタを解放した時は ポインタが指すノードへ%releaseを送信し ポインタが持っていた重みを返却する(図10.6 (2))。 %releaseを受信すると、 対応する輸出表エントリの重みから返却された重みを引く。 引いた結果ゼロになったならば輸出表エントリを解放する。
%releaseはsend_release()関数(runtime/cntlmsg.c)を 呼び出すことにより行われる。このメッセージを受けた場合には、 対象オブジェクトを輸出表から外す。その結果、もしそのデータが そのノード内でも参照されていなければ、次のGCではゴミになる。
これらの処理は、データをencodeする関数encode_data() (runtime/datamsg.c) exref classについては、 データ送信時に呼びだされるencode methodにより 以下のように実装されている。
|
file=rok_split_export.eps,width=6.5cm
file=rok_release_exref.eps,width=6.5cm
|