LoginSignup
3
2

More than 3 years have passed since last update.

OpenSiv3Dで非同期処理をする

Posted at

OpenSiv3Dで非同期処理をする

久し振りに C++を触り、OpenSiv3D で単純な非同期の処理をした際に色々知らなかったことが多かったので忘れないうちに備忘録として書いておきます。バージョンは OpenSiv3D 0.4.1です。タイトルにデカデカと入れといてなんですが、あまりOpenSiv3D要素はありません。

最小コード

時間がかかる関数を heavyFunction() を非同期で実行し、計算中は "計算中..." と表示し計算が完了したら結果を表示するコードは以下のようになります。

# include <Siv3D.hpp> // v0.4.1
# include <future>

double heavyFunction() {
    // 何か重い処理
    System::Sleep(3s);
    return 1.0;
}

// 非同期関数の結果をOptional型で返す関数
template<class T>
Optional<T> resultOr(std::shared_future<T> task) {
    if (task.valid()) {
        auto status = task.wait_for(0s);
        if (status == std::future_status::ready) {
            return task.get();
        }
    }
    return none;
}

void Main() {
    const Font font(24);
    std::shared_future<double> task = std::async(std::launch::async, heavyFunction).share();

    while(System::Update()) {
        font(resultOr<double>(task).map(Format).value_or(U"計算中...")).draw();
    }
}

std::shared_futuresharedstd::future みたいな感じです。(これ以上説明できません)

関数 Optional<T> resultOr(std::shared_future<T> task) は Siv3Dの Optional型を返り値とし、 std::shared_future の処理が完了していたら std::shared_future::get() し、そうでなければ、 none を返す関数です。
task.wait_for(0s) の部分はメインスレッドをブロックせずにタスクの状態を取得する為 0s ウェイトしている様です。

C++ 無限に知らないことが出てくるから怖い。正直これがベストプラクティスだとは思っていないので マサカリお待ちしております。
個人的には OpenSiv3Dに JavaScript/TypeScriptPromise 並に扱いやすい非同期処理まわりのラッパがあると嬉しいかも?
最近は3Dの機能も着々と実装され増々便利になっています!

OpenSiv3Dはいいぞ!

参考

AziOGroup Lab,: std::asyncで開始したスレッドの終了確認 [C++]
std::future as a parameter to a function C++ - Stack Overflow

3
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2