* KH-FDPLのメモ #0001 (途中からpersistent-Cのメモ)
-(by [[K]], 2016.02.04)
** 2016.02.04(木)
-とにかく作ることにする。どこから作るかを考えたのだけど、とにかくオブジェクトを操作できるようにしたい。そういうライブラリから作る。言語仕様を考え始めると気が遠くなるので、まだ考えないことにする。
** 2016.02.17(水)
-さっそく予定を変更(笑)。まあ私にはよくあること。・・・変数を永続化させる機能だけを取り出して、それを実装することにします。それで変数の永続化について体験できる環境を作ります。
--このサブプロジェクトを「persistent-C」「KHPC」と呼ぶことにします。
---http://khfdpl.osask.jp/wiki/?persistent_C
---http://khfdpl.osask.jp/wiki/?KHPC
** 2016.05.10(火)
-今日はwikiをたくさん更新しようと思ったら、いきなりたくさん荒らされてしまいました。近日中に荒らし対策スクリプトを入れるので、それまでは荒らされたページを凍結しておくことにします。
** 2016.05.11(水)
-よし、とりあえず荒らし対策完了。ぜんぜん完璧じゃないけど、昨日のパターンにはやられないはず。
** 2016.05.12(木)
-もうやられなくなったっぽい。よかったよかった。じゃあ開発しよう。
** 2016.05.13(金)
-今日はやられた!・・・また別の対処法を考えなくては。
-よし対処したー。
-今日はコードもそれなりに書けたのでいい日だー。
** 2016.05.16(月)
-loadしてないうちからsaveを実行しようとした場合はエラーにしよう。そうでないと、ただのloadし忘れの場合に、同じidの変数名があったら上書きされてしまって、悲しいことこの上ないから。
** 2016.05.17(火)
-(1)今日は、なるほどなーと思うことを発見した。以下に示すプログラムは永続変数の典型例だけど、これは間違っていた。
[間違った例]
persistent int sum = 0, i = 0;
persistent_load();
for (; i <= 100; i++) {
sum += i;
persistent_save(0);
}
printf("sum=%d\n", sum);
-正しい書き方はこうなる。
[正しい例]
persistent int sum = 0, i = 0;
persistent_load();
for (; i <= 100; i++) {
persistent_save(0);
sum += i;
}
printf("sum=%d\n", sum);
-違うのはsaveの位置だ。
-そんな違いがなぜ重要なのかを書こう。・・・仮に[間違った例]のプログラムが最後まで走ったとする。その場合、ファイルに書かれた変数の値はi=100, sum=5050になる。この状態でこのプログラムをもう一度実行すれば、i<=100を満たすのでループの中に入って、sum=5150に更新されて保存される。さらにもう一度実行したら、sum=5250になる。・・・つまりこのプログラムは期待通りに動いていない。
-一方で、[正しい例]なら最後に書かれる値はi=100, sum=4950になるので、何度実行しても結果はsum=5050となり、期待通りになる。
-もしloadするたびに1回だけループを回るという挙動が気持ち悪いのであれば、printfの直前にもsaveを入れるといい。そうすればi=101, sum=5050が保存されるので、次回起動時にforループに侵入しなくなる。
-この問題をより一般的に考えてみる。
while (i <= 100) {
persistent_save(0);
sum += i;
i++;
}
-これはforループをwhileに開いたものだ。こうして見ると、sum += i;の直後にsaveを入れるというのは、ループの処理を中途半端にやって途中で保存しているという行為に他ならず、それでは再開時に中途半端な処理をもう一度実行することになってしまうのは自明である。
--この問題さえなければ、saveがループの先頭にあってもループの末尾にあっても問題はない。
~
-(2)persistentな変数が今いくつになっているのか、いちいちプログラムを作って確認しなければいけないのは不便なので、簡単なツールを作ってみた。
khpc000>pbdtol dump p-vars.pbd
format: persistent_binary_memimage_IA32_v00
note: @hkawai3.khpc000.test
i (4bytes) (flags=0x00000000) :
64 00 00 00 (=100)
sum (4bytes) (flags=0x00000000) :
56 13 00 00 (=4950)
--よしよし。まあ最初はこんなものだろう。
~
-(3)persistent-Cを使っていると、変数がとても便利に思えてくる。・・・たとえばprintf("hello");というのは、画面表示が最も分かりやすいからサンプルに使われるのだと思う。でも、persistent-Cなら画面表示するよりも変数に代入しておく方が便利だ。
-変数に代入してsaveしておけば、画面に出したくなった時はツールを使っていつでも出せるし、リダイレクトでファイルに出すこともできる。この時点でprintfするプログラムと同等だ。その上に変数として使えるので、関数に渡したり、複雑な処理をしたりできる。
-通常のprintfなプログラムがあってソースコードがないとしたら、出力結果を変数に取り込むには、出力結果をファイルに出させて、ファイルをfopenしてfreadしなければいけない。
** 2016.05.18(水)
-とりあえず、ここでいったんリリース。
--http://khfdpl.osask.jp/download/khpc000a.zip
** 2016.05.25(水)
-KHPC ver.0.01のソースコード変換のコアはできたっぽい。
-あとちょっとでリリースかな。
** 2016.06.15(水)
-KHPCで永続変数を使ってプログラム間通信をもっとうまくやれないかなと考えているが、やはり面倒な手順が必要になってしまう。お手軽にやるならpersistent_loadLock()という関数を作って、これをloadの代わりに使わせることで、ロード直前にセーブファイルに対してロックを取らせて、save時にロックを自動解放するようにすることができる。これならload時にロックが取れるまで待つことになるので、上書きのアクセス競合は発生しない。お手軽でもある。しかしこのようなロック操作はC言語の標準関数だけでは記述できないので、ライブラリが機種依存してしまい、ちょっとまだやる気にはなれない。
-そもそもKHPCやpersistent-Cはプログラム間通信をメインに開発したものではなく、メインは変数の保存・復元やデバッグ支援である。おまけの用途のためにどこまで頑張るかは難しいところだと思う。プログラム間通信を本気でうまくやりたいなら、やはり最初からそれを目的に設計して開発するべきだと思う。
--そしてプログラム間通信はKHPCの主目的ではないので、これが完全にうまくできないからといって、それでKHPCがダメだということにはならない。
-お、また荒らしさんが来た・・・。うーん、対策コードの隙間をくぐり抜けてきたか・・・。
* こめんと欄
#comment