xrea-banner xreaad

超スマート・ポインタ

namespace kilrey; / C 言語, C++ / 自作ライブラリ / 超スマート・ポインタ

少しずつ手を加えては止めてを繰り返して来た 超スマート・ポインタをそろそろ公開しようと思います。 基本的には参照カウント式のスマート・ポインタです。 ただし普通のスマート・ポインタと違って 循環参照を解決することが出来ます。 そのためグラフのように相互参照を含んだ 複雑なデータ構造に対しても気軽に利用出来ます。 循環参照の解決には 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++ 版は作成中です。 自動で参照カウンタの上げ下げをするので だいぶ便利になると思います。