DXライブラリを使った非同期ファイルロード(真)
DXライブラリが公式に非同期読み込みに対応したので、それについての情報を纏めておく。
コレhttp://homepage2.nifty.com/natupaji/DxLib/function/dxfunc_other.html#R21N1
に関する注意事項。
LoadGraph等を実行した時点でのフラグで動作する
SetUseASyncLoadFlag( TRUE );の後に対応関数を呼び出した場合、たとえ途中でSetUseASyncLoadFlag( FALSE );にされた場合であっても非同期読み込みが継続される。
SetUseASyncLoadFlag( TRUE ); // 非同期読み込みフラグON int a = LoadGraph("a.png"); // 非同期読み込み終わるまでは無効なハンドルが返る SetUseASyncLoadFlag( FALSE ); // 非同期読み込みフラグOFF int b = LoadGraph("b.png"); // 同期読み込みなので有効なハンドルが返る
読み込み待ちはメインスレッドで
CheckHandleASyncLoad(...);で読み込み終了までwhile(...)等で待つ場合、おそらくハンドル生成等の部分をメインスレッドのProcessMessage()で行なっているため、
while( CheckHandleASyncLoad(handle) != FALSE ){ ProcessMessage(); Sleep(1); }
のような事をする必要がある。
Direct3D9 はマルチスレッド対応モードで起動すると動作が凄く重くなるので マルチスレッド非対応モードで起動して、SetUseASyncLoadFlag( TRUE ) ; の設定で LoadGraph を行った場合も Direct3D9 の操作が必要な処理だけ メインスレッドの ProcessMessage の中で処理するようにしています なので ProcessMessage を呼ばないと Direct3D9 の操作が必要なところで 処理が止まってしまうというわけです
という事らしい。
2012/04/17追記
struct Loader{ std::map<std::string,int> handle_map; bool Load(std::string filename) { SetUseASyncLoadFlag(TRUE); int handle = LoadGraph( filename.c_str() ); SetUseASyncLoadFlag(FALSE); if( handle == -1){ return false; } handle_map.insert( std::make_pair( filename, handle ) ); return true; } int Get(std::string filename) { auto it = handle_map.find( filename ); // ハンドルがあるなら、ロード終わっているか見てハンドルを返す if(it != handle_map.end() ){ int handle = (*it).second; while( CheckHandleASyncLoad(handle) != FALSE ){ ProcessMessage(); Sleep(1); } return handle; } //ハンドルがないなら、 else{ if( Load(filename) ){ return Get(filename); } else{ return -1; } } } } };
みたいなLoaderクラス介してやれば、事前読み込みしてから使う時にはロード時間なし、もし読み込み終わってないで使おうとしたら同期的な動き、みたいな事が出来て幸せになれるんじゃないですかね。
ところでWindowsでマイクロ秒程度のSleepってどうやるんですかね(血涙