Re: マルチスレッドとSetUseASyncLoadFlag ( No.1 ) |
- 名前:管理人 日時:2013/09/07 14:28
SetUseASyncLoadFlag の設定は全スレッド共通ですので( というかDXライブラリは
複数スレッドからライブラリの関数を呼ばれることを想定していないので )、
恐らく作成したスレッドで FileRead系の関数を呼んだ時点で SetUseASyncLoadFlag( FALSE ) ;の
状態になっていたのではないかと思います
> もしくは、図々しい限りで申し訳ないんですが、1度呼ぶだけで非同期でopen→readなど→closeまで面倒を
> 見てくれる関数を実装していただけないでしょうか?
その関数良いかもと思ったのですが、ファイルの内容を格納するメモリはどうしましょう?
ファイルサイズを取得するのも非同期で行うとすると、結局非同期でファイルサイズ取得が終了するまで待ってから
ファイルサイズ分のメモリを確保し、その後ファイル読み込みを非同期で行うということになると、
結局ステップが減るだけであまり恩恵は無い( 非同期処理の管理はそんなに楽にならない )ような気がします・・・
|
Re: マルチスレッドとSetUseASyncLoadFlag ( No.2 ) |
- 名前:てらす 日時:2013/09/09 23:08
お疲れ様です。
回答ありがとうございます。
やはり、たまたまそうなっていただけなのですね。
そのままでは問題が出ること間違いなしなので、現在は各FileRead系関数の後に
while( CheckHandleASyncLoad( fileHandle ) == TRUE ){ Sleep( 1 ); }
を追加して対応することにしました。
FileRead系関数実行中にメインスレッドでSetUseASyncLoadFlagが呼ばれた時や
複数のスレッドから同時にFileRead系関数が呼ばれた時に
正常に動作するか不安では有りますが・・・
現在作っているゲームの設計上、FileRead系関数が複数同時に呼ばれることはなく、
今のところは特に問題なく動いているので、それを応急措置としてこのまま進めたいと思います。
(いずれ問題が出そうではありますが、ここで止まってもいられないので)
> その関数良いかもと思ったのですが、ファイルの内容を格納するメモリはどうしましょう?
> ファイルサイズを取得するのも非同期で行うとすると、結局非同期でファイルサイズ取得が終了するまで待ってから
> ファイルサイズ分のメモリを確保し、その後ファイル読み込みを非同期で行うということになると、
> 結局ステップが減るだけであまり恩恵は無い( 非同期処理の管理はそんなに楽にならない )ような気がします・・・
すいません。正直何も考えずに提案してしまっていたので、自分でも少し考えてみました。
ファイル読み込みとそのためのメモリ確保や開放はDXライブラリで行い、グラフィックやサウンドと同じようにハンドルを返し、
そのハンドルを使ってデータを受け渡すとかはどうでしょうか?
// ファイルを読み込み、ハンドルを返す
int XXXXLoad
(
const TCHAR *FileName // ファイルパス
);
// 読み込んだファイルからデータを受け取る
int GetXXXX
(
void *Buf, // データを受け取るバッファ
int Size, // 受け取るデータ量(*Bufのサイズ、バイト数)
int Offset, // データをどの位置から受け取るか(バイト数)
int XXXXHandle // XXXXLoadで受け取ったハンドル
);
// 読み込んだデータを消す
int DeleteXXXX(
int XXXXHandle // XXXXLoadで受け取ったハンドル
);
DXライブラリ的にはこんな感じでしょうか。
後は読み込んだファイルサイズを取得する関数を用意したりですかね。
プログラミングは全て独学でやってきているので、これで非同期の恩恵が受けられるのか、
実はFileRead系関数とやっていることは同じなんじゃないか、などと思い始めてよくわからなくなっていますが・・・
(DxLib_Endで開いたファイル全てに対してFileRead_closeしていたらやっていることはほとんど同じですよね)
|
Re: マルチスレッドとSetUseASyncLoadFlag ( No.3 ) |
- 名前:管理人 日時:2013/09/13 01:10
ご提案して頂いた機能を実装してみました
<追加した関数>
// 指定のファイルの内容を全てメモリに読み込み、その情報のアクセスに必要なハンドルを返す
// ( 戻り値 -1:エラー -1以外:ハンドル )
// 使い終わったらハンドルは FileRead_fullyLoad_delete で削除する必要があります
int FileRead_fullyLoad( const TCHAR *FilePath ) ;
// FileRead_fullyLoad で読み込んだファイルのハンドルを削除する
int FileRead_fullyLoad_delete( int FLoadHandle ) ;
// FileRead_fullyLoad で読み込んだファイルの内容を格納したメモリアドレスを取得する
void * FileRead_fullyLoad_getImage( int FLoadHandle ) ;
// FileRead_fullyLoad で読み込んだファイルのサイズを取得する
LONGLONG FileRead_fullyLoad_getSize( int FLoadHandle ) ;
<Test1.bmp を非同期で読み込んで画面に表示するサンプルプログラム>
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int ghandle ;
void *image ;
int size ;
int fhandle ;
// ウインドウモードで起動
ChangeWindowMode( TRUE );
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1;
// ファイルの非同期読み込み
SetUseASyncLoadFlag( TRUE ) ;
fhandle = FileRead_fullyLoad( "Test1.bmp" ) ;
SetUseASyncLoadFlag( FALSE ) ;
// 読み込み終了待ち
while( ProcessMessage() == 0 && CheckHandleASyncLoad( fhandle ) ){ Sleep( 1 ) ; }
// 読み込んだ内容が格納されているメモリ領域の先頭アドレスとファイルサイズの取得
image = FileRead_fullyLoad_getImage( fhandle ) ;
size = FileRead_fullyLoad_getSize( fhandle ) ;
// グラフィックハンドルの作成
ghandle = CreateGraphFromMem( image, size ) ;
// 読み込んだファイルの解放
FileRead_fullyLoad_delete( fhandle ) ;
// 画面に作成したグラフィックハンドルで描画
DrawGraph( 0, 0, ghandle, TRUE ) ;
// キー入力待ち
WaitKey() ;
// DXライブラリの後始末
DxLib_End();
// ソフトの終了
return 0;
}
非同期処理待ちが一度で済むのが利点です
確かに open, seek, tell, read それぞれに非同期処理終了待ちするより処理効率も良さそうです
こちらにアップしましたので、よろしければお試しになってみてください m(_ _)m
http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_DevCppTest.exe // Dev-C++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibGCC_MinGWTest.exe // MinGW 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibDotNet.zip // .NET用
http://homepage2.nifty.com/natupaji/DxLib/DxLibMakeTest.exe // ソース
(中身を既存のライブラリのファイルに上書きして、BCCをお使いの
場合は『再構築』を、VCをお使いの場合は『リビルド』を、
Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい)
|
Re: マルチスレッドとSetUseASyncLoadFlag ( No.4 ) |
- 名前:てらす(解決) 日時:2013/09/13 23:08
お疲れ様です。
実装された関数を試したところ、私の目指していたものを妥協なしに再現することが出来ました。
使い勝手もよく、これでファイルの種類を気にせずに非同期読み込みを行うことが出来ます。
お忙しい中、本当にありがとうございました。
|