少しずつ手を加えては止めてを繰り返して来た 超スマート・ポインタをそろそろ公開しようと思います。 基本的には参照カウント式のスマート・ポインタです。 ただし普通のスマート・ポインタと違って 循環参照を解決することが出来ます。 そのためグラフのように相互参照を含んだ 複雑なデータ構造に対しても気軽に利用出来ます。 循環参照の解決には Concurrent Cycle Collection in Reference Counted Systems のアルゴリズムを利用しています。 ただし C 言語特有の問題のために 解放や排他などをちょっとアレンジしました。
対応環境は ansi C strict+pthread です。 ちなみに一時は Win 対応もしようとしていましたが結局止めました。 普段の開発が Linux なので勝手が判らないというのが主な原因です。 Win に馴れている人に移植してもらえると嬉しいです。 ちなみにライセンスは MIT LICENSE ではなく LGPL です。 このライブラリを改造したライブラリを公開するときは ソースコードも公開する必要があります。 (download)
それではインストールの仕方です。展開後のディレクトリで
./configure
make
sudo make install
としてください。 /usr/local 以下にインストールされます。 インストール先を変えるには
./configure --prefix=/home/kilrey/usr/local
というように指定してください。 その他のオプションは GNU autoconf/automake に準じます。
それでは利用法です。 まず主ライブラリは libkgc.so です。 これと libpthread.so をリンクしてください。 gcc ならば -pthread を使うと良いと思います。 次にヘッダです。 kgc.h を include してください。
コードの書き方は
#include "kgc.h"
int main() {
kvtable_t* vtblp = kvtable_new(func_del, func_sweep);
kcycle_init();
{
target_t* tgtp = (target_t*)malloc(sizeof(target_t));
kpointer_t* kptrp;
target_init(tgtp);
kptrp = kpointer_new(tgtp, vtblp);
kpointer_increment(kptrp);
/* 実際の操作 */
kpointer_decrement(kptrp);
}
kcycle_process_cycles();
kcycle_process_cycles();
kcycle_exit();
}
という感じです。 まず kvtable_t を生成します。 kvtable_t は中身のオブジェクトを削除する関数 (func_del()) と 中身が持つ kpointer_t を巡回する関数 (func_sweep()) です。 詳しくは kvtable.h を読んでください。 次に kcycle_init() を呼んで 循環参照解決用のメモリ領域などを生成します。 中身のオブジェクトを生成した後で kpointer_t を生成します。 kpointer_t に渡すのは中身のオブジェクトへのポインタと そのオブジェクトに対応した kvtable_t です。 後は参照が増える度に kpointer_increment() 、 減る度に kpointer_decrement() を実行してください。 自動で参照カウンタの上げ下げをするようには なっていないので注意してください。 ただし func_del() 内では中身が参照する kpointer_t について kpointer_decrement() はしないでください。 func_sweep() を経由して kpointer_decrement() されるので 二重に参照を減らすことになってしまいます。 最後に循環参照を回収するために kcycle_process_cycles() を呼びます。 呼び出しの最後に循環参照を検出して 次の呼び出しの最初にその循環参照を解放するという仕組みです。 ある時点で確実に回収したい場合には 二回続けて呼び出すようにしてください。 最後に kcycle_exit() を呼んで 循環参照解決用のメモリ領域などを破壊します。
ちなみに C++ 版は作成中です。 自動で参照カウンタの上げ下げをするので だいぶ便利になると思います。