##今回作るもの
裏で処理しながらローディング画面を出す
なぜDirectX"9"なのか。
「課題要件」です
環境
Visual Studio 2015
DirectX SDK (June 2010)
Intel® Core™ i7-4810MQ
準備
まずはThreadが使用できなければ始まりません。
スレッド数はstd::thread::hardware_concurrency()
で確認できます。
快適なデバックを行うにはmain+VisualStudio+osで3スレッド必要です。
今回専有しないので考慮しませんが、スレッドを専有する場合はosなどの他のプログラムを考慮する必要があります。
auto count = std::thread::hardware_concurrency();
if (count < 3)
{
//Err
}
裏処理
マルチスレッドで処理を行う場合、複数スレッドに跨るデータをスレッドセーフにする必要があります。
今回だとロードの終了を通知するフラグを、スレッドセーフに扱う関数を定義します。
bool isLoaded = false;
std::mutex isLoadedMutex;
void SetLockFlag(bool _)
{
std::lock_guard<std::mutex> lock(isLoadedMutex);
isLoaded = true;
}
bool GetLockFlag()
{
std::lock_guard<std::mutex> lock(isLoadedMutex);
return isLoaded;
}
void AsyncLoad()
{
//ダミーで10秒待つ
auto sleepTime = std::chrono::seconds(10);
std::this_thread::sleep_for(sleepTime);
SetLockFlag(true);
}
Thread起動
このステートメントを実行すると同時に非同期関数が起動します。
std::thread th(AsyncLoad);
完了通知
if (!GetLockFlag())
{
//ロード中
}
else
{
//ロード完了
}
後始末
Threadはそのデストラクタが呼ばれる前に、joinまたはdetachを呼ぶ必要があります。
今回はjoinを行いスレッドが終了するのを待機していますが、detachにすると
Threadのデストラクタ後も関数が走り続けます。
th.join();
##注意点
・データ競合
データの書き込みと読み込みが同時に行われると発生します。
運が良ければどこかでクラッシュとして拾われますが、悪ければ顕著化せずに埋もれてしまい探し出すのに非常に労力を要します。
・DirectX9のデバイスについて
残念ですが、DirectX9のデバイスはスレッドセーフではありません。
そのため、レンダリングしながら裏で(デバイスを使用した)ロードと言うのは不可能です。
参考文献
・DirectXのデバイスのスレッドセーフ性について:
https://msdn.microsoft.com/ja-jp/library/ee422106(v=vs.85).aspx
・データ競合:
http://yohhoy.hatenablog.jp/entry/2013/12/15/204116
・C++11のスレッド:
http://www.slideshare.net/hotwatermorning/c-38563753
今回のプロジェクト