スレッドについて

スレッドフレームワーク

ライブラリは、ファイル読み込みや音声データ再生処理を、アプリケーションと並列に効率的に実行できるよう、スレッドシステムを使用しています。
ライブラリは「スレッドフレームワーク」に従って動作しており、アプリケーションの要求に合わせて、スレッドフレームワークのタイプ「スレッドモデル」を指定することができます。

スレッドモデルには3つのタイプがあります。
ライブラリ初期化用のコンフィグ構造体( CriAtomExConfig )の thread_model メンバでスレッドモデルを指定します。

スレッドフレームワークの種類
スレッドモデル 説明 初期化定数
マルチスレッドフレームワーク ライブラリでスレッド作成 CRIATOMEX_THREAD_MODEL_MULTI
ユーザマルチスレッドフレームワーク アプリでスレッド作成 CRIATOMEX_THREAD_MODEL_USER_MULTI
シングルスレッドフレームワーク スレッド未使用 CRIATOMEX_THREAD_MODEL_SINGLE



いずれのスレッドモデルでにおいても、フレームワークを正しく動作させるには、「定期的にサーバ処理関数を実行する」ことが重要となります。

マルチスレッドフレームワーク

初期化処理時にマルチスレッドフレームワークを選択した場合、ライブラリは内部的にスレッドを作成し、スレッド上で音声データのデコードやファイルアクセスを行います。
マルチスレッドフレームワーク使用時は、サーバ処理関数として criAtomEx_ExecuteMain 関数 を定期的に実行する必要があります。
(デコード処理やファイルアクセス完了待ち等、時間のかかる処理は全てライブラリが作成したスレッド上で実行されますが、極短時間で終わる処理がいくつか実行される可能性があります。)
デフォルトのスレッド優先度は THREAD_PRIORITY_HIGHEST です。


criatom_library_multi_thread_async.png
マルチスレッドフレームワークの概念

ユーザマルチスレッドフレームワーク

ライブラリ内部ではスレッドを作成せず、アプリケーションの作った別スレッドからサーバ処理を呼び出すためのフレームワークです。
注意:
ADX2 LE では動作の保証対象外となりますので、使用しないでください。

シングルスレッドフレームワーク

初期化処理時にシングルスレッドフレームワークを選択した場合、ライブラリはスレッドを作成しません。
また、サーバ処理が複数スレッドから同時に実行されることを想定しないため、共有リソースへアクセスも排他制御されません。
シングルスレッドフレームワーク使用時は、サーバ処理関数として criAtomEx_ExecuteMain 関数 を定期的に実行する必要があります。
マルチスレッドモード時の criAtomEx_ExecuteMain 関数とは異なり、呼び出したスレッドでサーバ処理が実行されます。
criAtomEx_ExecuteMain 関数内でオーディオ、ファイルアクセス、データ展開処理のすべてを行うため、処理時間が1Vを超える可能性があります。)
criatom_library_single_thread.png
シングルスレッドフレームワークの概念
注意:
シングルスレッドフレームワーク時にファイル読み込みを行うと、criAtomEx_ExecuteMain 関数の処理時間はほとんどの場合1Vを超えます。
ストリーム再生を行う場合はシングルスレッドフレームワークを使用せず、他のフレームワークを選択してください。

スレッドセーフかどうか

モジュールごとの安全性
ライブラリの関数がスレッドセーフにできているかどうかは、モジュールによって異なります。
モジュールごとのマルチスレッドアクセスへの対応状況は以下のとおりです。
マルチスレッドアクセスへの対応状況
モジュール スレッドセーフかどうか 補足
CriAtomEx API スレッドセーフではありません 一部例外的にスレッドセーフな関数もあります(後述)
CriAtomExPlayer API スレッドセーフではありません 1つのハンドルを複数のスレッドから同時にアクセスした場合、問題が発生します
CriAtomExVoicePool API スレッドセーフではありません 1つのハンドルを複数のスレッドから同時にアクセスした場合、問題が発生します
CriAtomExAcb API スレッドセーフではありません 1つのハンドルを複数のスレッドから同時にアクセスした場合、問題が発生します
CriAtomPlayer API スレッドセーフではありません 1つのハンドルを複数のスレッドから同時にアクセスした場合、問題が発生します
CriAtomAwb API スレッドセーフではありません 1つのハンドルを複数のスレッドから同時にアクセスした場合、問題が発生します
CriAtomHcaMx API スレッドセーフではありません 1つのハンドルを複数のスレッドから同時にアクセスした場合、問題が発生します
CriAtomAsr API スレッドセーフではありません 1つのハンドルを複数のスレッドから同時にアクセスした場合、問題が発生します
CriErr API スレッドセーフではありません  


複数ハンドルを使用する場合
スレッドセーフではないAPIを呼び出すケースでも、スレッド毎に異なるハンドルを使用している場合は、同じ関数を同時に実行しても問題ありません。
例えば、 criAtomExPlayer_SetCueId 関数はスレッドセーフではありませんが、スレッド毎に異なる CriAtomExPlayer ハンドルを作成して、 criAtomExPlayer_SetCueId 関数を呼び出すことは可能です。

具体的な例としては、以下のようなケースが挙げられます。
void thread_func1(void)
{
    CriAtomExPlayerStatus player_status;
    player_1 = criAtomExPlayer_Create(&player_config, NULL, 0);
    criAtomExPlayer_SetCueId(player_1, acb_hn, CRIATOMEX_CUE_BOMB2);

    for (;;) {
        player_status = criAtomExPlayer_GetStatus(player_1);
        if (player_status == CRIATOMEXPLAYER_STATUS_PLAYEND) {
            break;
        }

        criAtomEx_ExecuteMain();
        sleep(10);
    }
    criAtomExPlayer_Destroy(player_1);
}

void thread_func2(void)
{
    CriAtomExPlayerStatus player_status;
    player_2 = criAtomExPlayer_Create(&player_config, NULL, 0);
    criAtomExPlayer_SetCueId(player_2, acb_hn, CRIATOMEX_CUE_THUNDER3);

    for (;;) {
        player_status = criAtomExPlayer_GetStatus(player_2);
        if (player_status == CRIATOMEXPLAYER_STATUS_PLAYEND) {
            break;
        }

        criAtomEx_ExecuteMain();
        sleep(10);
    }
    criAtomExPlayer_Destroy(player_2);
}



上記コード中の thread_func1 と thread_func2 が2つのスレッドで同時に実行されたとしても、特に問題は発生しません。
例外的にスレッドセーフな関数
モジュール自体がスレッドセーフではない場合でも、以下の関数は例外的にスレッドセーフにできています。

これらの関数は、同一モジュールの他の関数と同時に実行した場合でも、問題なく動作します。
リソースの解放に関する注意
ライブラリの終了処理( criAtomEx_Finalize_WASAPI 関数)や、ハンドルを破棄する関数( criAtomExPlayer_Destroy 関数等)は、すべてのライブラリ(ハンドル)リソースを解放します。
そのため、たとえスレッドセーフな関数を実行中であっても、別スレッドでこれらの関数を実行した場合には、アクセス違反等の重大な問題を引き起こす可能性があります。


CRI Middleware logo Copyright (c) 2012-2018 CRI Middleware Co., Ltd. CRI ADX2 LE マニュアル (for Cocos2d-x) SDKVer.2.10版