ハンドルベースのリソースマネージャに対する考察 part2
前回の記事(http://d.hatena.ne.jp/studiokingyo/20060406#p1)
その昔・・・メモリリソースに関してプログラミングをはじめた当初からケチケチ主義だった私はgoogle:コンパクションという機能を知ってからコンパクションを自分で実装したい思いに駆られていた。
C言語をやっと覚えてgoogle:DxLibを使えるくらいのスキルになった当初・・・実は、コンパクション機構を作っていたことがあった。*1
コンパクションといえばOSに実装されているような高度な機能だ。*2これを実際に考えてC言語のみで作ろうとした自分もアホだが・・・
なぜならC言語でコンパクション機構はどうがんばっても作れない。理由はコンパクション後メモリアドレスが無効になってしまい、そのメモリアドレスの保存先の変数を更新できないからだ。*3
これをどうにか解決しようと様々なアプローチをしたわけだが、そこで誕生したデータ構造がarray_onebyoneだった。いわいるこれがハンドルベースのリソースマネージャー(以下RM)という事に気付くのは数年後だったわけだが・・・
しかしながら、array_onebyoneの場合、開放時にハンドルを二回解放してしまうと既に使用している領域に対しても解放しているとの意味になってしまいこの機構は二重解放をしないという絶対条件(D言語で言う契約の時に使う条件のような)の元のみでしか使えない少々厄介な機構であった。
そのような機構であるが、実際に私のプログラム内で使ったことがある。それがgoogle:BMLDLLだ。array_onebyoneを使ったのだがBMLDLLを実行中、数分後・・・落ちてしまうのだ。原因不明・・・。どんなにデバッガかけても再現不能・・・。
例の二重解放がどこかで行われているのだ・・・。*4
このような経験から、array_onebyoneは安全性という面に関してかなりの疑問が残る体験をしてしまった。これ以降、私はその手のRMには単純なフラグ形式が良いのではないかという事に落ち着いている。*5
フラグ形式の場合、空き領域を探索するのに単純な方法だと線型探索をとってしまうが、array_onebyoneの機構とあわせたり、hash法などのアプローチを使用してやれば空き領域探索も速くなるのではないかと感じる。
また、google:dynamic_bitset的な機構も利用してやればフラグ用メモリの削減も出来る。
しかしながら、マルチスレッド環境でフラグ形式の機構を使う場合フラグを上げ下げする際にスレッドをロックしなくてはならない。ただフラグ上げ下げだけにこうしてしまうのは大げさな気がするのだ。
なので、ここで、フラグ形式にする場合、高速化の見返りに「RMが生成されたスレッドのみでしかそのRMを操作できない」という絶対条件を加えてやればよいのではないかと感じた。
yaneSDK3rdでいうThreadLocalな環境である。*6
この方がまだ二重解放よりはバグの発見はしやすい。(例えば、RM生成時のThreadIDを保存しておき、それとCurrent ThreadIDを比較するなどしてチェックする。)
だが、この世には意外と身近な所に便利なハンドルベースのRMライブラリが存在していたのだ。私はこの事に気付いた時本末転倒だと感じた。感のよい人であれば既にそのRMライブラリを予測できることだろう。
続く・・・。