Weakポインタとオブジェクト回収イベント
Scheme処理系には大抵WeakポインタのためのAPIが有ると思ってたけど、たまに無いのもあるようで。。
バイナリパッチのためのフレームワークを作る必要が有って、オブジェクトのメタデータを格納するための良い方法と言えばweak hashtableなので対応状況を調べている。(多くのプロトコルでは、パケットは入れ子構造をしているので、取り出した構造体について、どの構造体やパケット、ファイルに由来するかどうかをクエリする手段が必要になる。)
多くの処理系はweak-vectorかweak-pairのどちらかを備えている。Racketはweak-boxを採用している。
原理的には、これらのどちらかが存在すればweak hashtableは作ることができる。(適当なカウンタをキーにしてweak-pairを指す普通のハッシュテーブルを作り、定期的に手動でコンパクションする)
いくつかのSchemeはオブジェクトアノテーション専用のAPIを持っている。
GuardianとWillと回収イベント
weakプリミティブで普通にweak-hashtableを作ると、何らかの方法で手動でコンパクションする必要が生じる。そのコンパクションも、普通のGCと同じように全キーをトラバースしないといけないのであまり効率が良くない。
GCによって一旦回収されたオブジェクトを再度受けとって"復活"させ、どのオブジェクトが回収されたのた直接わかると便利で、それに使用できる仕組みとしてguardianとかwillが知られている。
nmoshは、イベントキューにGC回収イベントを積ませることができる。そもそもBoehmGCの仕組み上、GCがどのスレッドで走るか確定できないので、スレッドセーフなイベントキューを一旦経由する必要がある。(この仕様により、ジェネリックなdestructorをGCの発動に合わせて起動させることができない。GCが発生するのがそもそもVMスレッド上とは限らないため。) 今は1オブジェクト1イベントで効率が非常に悪いので、複数イベントを投げられるように変更するつもり。
Racketのwill( http://docs.racket-lang.org/reference/willexecutor.html )はnmoshのように回収イベントを待ち合わせることができ、かつ、手動でのinvokeもできる。
ChezやGuileのGuardian( http://scheme.com/csug8/smgmt.html#./smgmt:h2 )は、もうすこしプリミティブ寄りと言える。Guardianオブジェクトには、GCの回収対象になっても"保護"するオブジェクトを覚えさせることができ、Guardianオブジェクト自体を評価することで、GCによって回収(対象としてマークされたが一旦guardianに保護)されたオブジェクトを取り出すことができる。