picogc raeding - arosh/arosh.github.com GitHub Wiki
https://github.com/kazuho/picogc
https://github.com/kazuho/picogc/blob/master/picogc.h#L198
picogcではGCのルートオブジェクトを複数持つことができるようになっているが,現在使われているルートオブジェクトが簡単に得られると便利である。gc_scope
はコンストラクタで現在のルートオブジェクトを保存,新しいルートオブジェクトで上書きし,デストラクタで古いルートオブジェクトを復元する。
簡単に言うと,ルートオブジェクトを複数持つ必要が無いならば,gc
オブジェクトを作った直後にpicogc::gc_scope gc_scope(&gc);
するだけでよい。
https://github.com/kazuho/picogc/blob/master/picogc.h#L175
テンプレート化しているのはODRを回避するためだと思う.ただし,template <bool T> config _globals<T>::default_config;
のような記述が必要となる理由がよく分からない.記述をコメントアウトすると,確かにコンパイルできなくなる.よく理解していないが,テンプレートの実体化あたりの話と関係があるような気がする.「テンプレート static」のようなキーワードで検索すると関係がありそうなページがいくつか見つかる.
14.6.2 明示的実体化 (Explicit instantiation) - C++11の文法と機能 (C++11: Syntax and Feature)
config _globals<T>::default_config
は使われていない.gc
のコンストラクタの引数は conf = globals::default_config
が正しいような気がする.
https://github.com/kazuho/picogc/blob/master/picogc.h#L288
コンストラクタとデストラクタでgc->scope_
を更新する。コンストラクタが呼び出されてからデストラクタで呼び出されるまでの間に作られたオブジェクトのマーキングを処理。
scope::close
の引数は初期のバージョン (ブログに載っているサンプル) では picogc::local<T>
だったが,途中のコミットから T *
に変わった。picogc::local<T>
だと何か問題があるのだろうか?
https://github.com/kazuho/picogc/commit/e76bdde1ece41d8a675817eb29286c1ba25ca447
https://github.com/kazuho/picogc/blob/master/picogc/util.h
ログ等の出力を行うクラスのインターフェース。picogc.h
の中では具体的な実装は無い。
https://github.com/kazuho/picogc/blob/master/picogc.h#L275
所有権をどうにかするっぽい?
スタックの実装。テンプレート化してあるけど,value_type
はgc_object *
だけ。
https://github.com/kazuho/picogc/blob/master/picogc.h#L59
メモリの確保・解放が頻繁に行われるのを防ぐためにVALUES_PER_NODE
の大きさ (デフォルトでは2048個) のvalue_type
の配列を単位としてメモリを確保している。また,スタックの要素数が,確保した領域がいっぱいになるか,ならないかの境界あたりで増減すると,やはりメモリの確保・解放が頻繁に行われてしまうので,reserved_node_
にキャッシュを作っている。これにより,1回のpush/popあたりのメモリの確保・解放の回数のオーダーがO(1/B)になる。このアルゴリズムには一般的な名前が付いていてもおかしくない気がする。
restore
は引数のvalue_type *slot
がtop
に来るまでの領域を解放する。
複数の箇所で::operator new
や::operator delete
という記述が見つかるが,これはplacement newと呼ばれる。newやdeleteも演算子のひとつであって,オーバーロードすることができるのである。
http://ppp-lab.sakura.ne.jp/cpp/language/036.html
GCの管理下に入れるオブジェクトを登録する方法として,最初に思いつくのはコンストラクタ内で登録関数を呼び出すことだが,この設計は間違いを犯しやすい。そのため,picogcではplacement newによってnewの呼び出しをフックし,その中で登録関数を呼び出す。
登録関数はgc::allocate
である。この関数では領域を確保した後,よく分からない処理をしている。