今、ブロックしないファイル読み込みをやっています。
普通にファイル読み込みを書いた場合、データを読み込む間はプログラムが止まります。
そこを止まらないように作りたいわけです。
まず、Request関数でファイルの読み込み要求を投げます。
あとは、Loading関数がtrueになるまで待機し、trueになったらGetBuffer関数でデータを得ます。
で、出来たのがこんな関数。
このUpdage関数は毎フレーム呼ばれることを想定して作成しています。
void Update(){
switch(state){
case 0:
file.Request("data.dat");
state++;
break;
case 1:
if (file.Loading() == false) state++;
break;
case 2:
config.LoadFromMemory(file.GetBuffer());
state++;
case 3:
file2.Request(config.StageName(stage));
state+;
case 4:
if (file2.Loading() == false) state++;
break;
case 5:
stage.LoadFromFile(file2.GetBuffer());
stageReady = true;
state++;
break;
default:
break;
}
}
しかし、この関数、非常に書いてて苦痛です。
上のソースにはこんな問題点があります。
・コードの追加や削除が面倒
・無駄に1フレーム待つ場所がある
コードに追加や削除をする度に全体のcaseの数値を書き換えなければなりません。
それに、ひょんなことからstate++ を2回書いてしまうというバグの混入が考えられます。
また、上記のプログラム、case 2,3,4まではわざわざbreakする必要がありません。
もっといえば、ファイル読み込みの部分にキャッシュが搭載されていて、
Requestを投げたらすぐにLoading関数がtrueを返す設計の場合、無駄に待っていることになります。
この辺を少し改善したソースがこの通り
void Update(){
switch(state){
case 0:
file.Request("data.dat");
case 1: state = 1;
if (file.Loading() == false) break;
case 2: state = 2;
config.LoadFromMemory(file.GetBuffer());
case 3: state = 3;
file2.Request(config.StageName(stage));
case 4: state = 4;
if (file2.Loading() == false) break;
case 5: state = 5:
stage.LoadFromFile(file2.GetBuffer());
stageReady = true;
default:state = 999;
break;
}
}
少し野暮ったいプログラムになりましたが、前のプログラムに会った
「無駄に待つ」、「state++を2回書いてしまう」という問題点は解決されました。
追加は相変わらず面倒ですが、stateが連番でなくても良いため削除は簡単になっています。
追加を楽にするために、1,2,3ではなく、10,20,30と番号をふったら良いかもしれません。
っていつのBASICや! RENUMよこせ、RENUM!!!
ということで、もっとスッキリ爽快なソースを紹介。
bool Update(){
CoroutineBegin();
file.Request("data.dat");
while(file.Loading()) yield;
config.LoadFromMemory(file.GetBuffer());
file2.Request(config.StageName(stage));
while (file2.Loading()) yield;
stage.LoadFromFile(file2.GetBuffer());
stageReady = true;
state = -1;
CoroutineEnd();
return true;
}
前回のコルーチンの登場です。
どうですか、このスッキリ具合。
ソースは短くなったし、追加、削除での番号振り直しもありません。
コルーチンの内部では暗黒儀式を行っているような気がしますが、
ほら、boostの内部でも暗黒儀式多いですしおすし。
私、脱いだらすごいんです、ということでひとつなんとか。