CRI ADX  Last Updated: 2024-07-17 10:47 p
About Thread

Thread Framework

CRI Atom library uses a thread system so that it can efficiently read files and play back sound data in parallel with the application.
CRI Atom library runs according to the "thread framework"; you can specify a "thread model", which is the type of the thread framework depending on the requirement of the application.

There are three thread models.
Thread model is specified using thread_model member of the configuration structure ( CriAtomExConfig ).

Types of Thread Framework
Thread Model Description Initialization Constant
Multithread framework (timer-driven) Threads creation by the library CRIATOMEX_THREAD_MODEL_MULTI
Multithread framework (user-driven) Threads creation by the library CRIATOMEX_THREAD_MODEL_MULTI_USER_DRIVEN
User multithread framework Threads creation by the application CRIATOMEX_THREAD_MODEL_USER_MULTI
Single thread framework Thread not used CRIATOMEX_THREAD_MODEL_SINGLE


In all thread models, it is important to "call the server process function periodically" for the framework to run correctly.

Multithread Framework

When a multithread framework (timer-driven) is chosen at initialization, the library creates threads internally and performs decoding of sound data and file access in these threads.
By default, the CRI Atom thread priority is THREAD_PRIORITY_HIGHEST.
The multithread framework is further broken down into two types depending on the threads' driving mechanism.
  • Timer-driven
  • User-driven
Timer-driven Multithread Framework
When timer-driven is specified, the Atom library runs threads at regular intervals to perform server processing.
Timer-driven Multithread Framework Concept
Attention
You must call the criAtomEx_ExecuteMain function at a regular interval as a server processing function, even when using the timer-driven method.
(Although all tasks that take time to complete, such as decoding or waiting for the completion of file access, are performed in threads, some tasks that can finish within very short time may also be performed.)
User-driven Multithread Framework
When user-driven is specified, threads are run when the user calls the criAtomEx_ExecuteMain function to perform server processing.
User-driven Multithread Framework Concept

User Multithread Framework

When user multithread framework is chosen at the time of initialization, the library does not create threads.
However, the library performs exclusive control for the access to shared resources so that the server process works correctly even when it is called simultaneously from two or more threads.
When user multithread framework is used, you must call the criAtomEx_ExecuteAudioProcess function periodically as a server process function.
Unlike the criAtomEx_ExecuteMain function for multithread mode, the server process runs in the calling thread.
  • The criAtomEx_ExecuteAudioProcess function performs tasks only for audio playback.
  • Application must call the ::criFs_ExecuteFileAccess function for file access.
    (In addition, when reading compressed data, it must call the ::criFs_ExecuteDataDecompression function.)
  • Although the criAtomEx_ExecuteAudioProcess function performs tasks equivalent to 1V, the time the ::criFs_ExecuteFileAccess and the ::criFs_ExecuteDataDecompression functions take varies depending on the size of data.
    Care must be taken when you call the ::criFs_ExecuteFileAccess or the ::criFs_ExecuteDataDecompression function in the main thread since it may cause dropping frames or stopping sounds.
User Multithread Framework Concept
Attention
If you want to perform streaming playback when user multithread framework is chosen, do not call the criAtomEx_ExecuteMain function.
(Since the criAtomEx_ExecuteMain function waits for the completion of file read, execution is locked in the function for several Vs.)
When performing streaming playback, you must call only the criAtomEx_ExecuteAudioProcess function in the main thread, and call the ::criFs_ExecuteFileAccess or the ::criFs_ExecuteDataDecompression function in the other threads.

Single Thread Framework

When single thread framework is chosen at the time of initialization, the library does not create threads.
Moreover, since the server process does not assume that it is called from multiple threads simultaneously, the library does not perform exclusive control for access to shared resources.
When single thread framework is used, you must call the criAtomEx_ExecuteMain function periodically as a server process function.
Unlike the criAtomEx_ExecuteMain function for multithread mode, the server process runs in the calling thread.
(Since the criAtomEx_ExecuteMain function performs all tasks such as audio and file access or data expansion, the processing time may exceed 1V.)
Concept of Single Thread Framework
Attention
If a file is read when single thread framework is chosen, processing time of the criAtomEx_ExecuteMain function will exceed 1V in most cases.
When you want to perform streaming playback, choose other frameworks instead of single thread framework.

Thread Safety

Safety of Each Module

Thread safety of functions in CRI Atom library depends on modules.
Support for multithread access by each module is as follows.

Support for Multithread Access
Module Thread Safety Note
CriAtomEx API Not thread-safe Some functions are exceptionally thread-safe (see below)
CriAtomExPlayer API Not thread-safe Problem occurs when single handle is accessed from multiple threads simultaneously
CriAtomExVoicePool API Not thread-safe Problem occurs when single handle is accessed from multiple threads simultaneously
CriAtomExAcb API Not thread-safe Problem occurs when single handle is accessed from multiple threads simultaneously
CriAtomPlayer API Not thread-safe Problem occurs when single handle is accessed from multiple threads simultaneously
CriAtomAwb API Not thread-safe Problem occurs when single handle is accessed from multiple threads simultaneously
CriAtomHcaMx API Not thread-safe Problem occurs when single handle is accessed from multiple threads simultaneously
CriAtomAsr API Not thread-safe Problem occurs when single handle is accessed from multiple threads simultaneously
CriErr API Not thread-safe

When Using Two or More Handles

Even in scenarios where API which is not thread-safe is called, calling the same function simultaneously does not generate problem when each thread uses different handles.
For example, although the criAtomExPlayer_SetCueId function is not thread-safe, it is possible that each thread creates different ::CriAtomExPlayer handles and calls the criAtomExPlayer_SetCueId function.

The following is a specific example.
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;
}
sleep(10);
}
}
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;
}
sleep(10);
}
}
void criAtomExPlayer_Destroy(CriAtomExPlayerHn player)
Destroy an AtomEx player.
void criAtomEx_ExecuteMain(void)
Execute the server processing.
CriAtomExPlayerStatus criAtomExPlayer_GetStatus(CriAtomExPlayerHn player)
Get the player status.
CriAtomExPlayerHn criAtomExPlayer_Create(const CriAtomExPlayerConfig *config, void *work, CriSint32 work_size)
Create an AtomEx player.
void criAtomExPlayer_SetCueId(CriAtomExPlayerHn player, CriAtomExAcbHn acb_hn, CriAtomExCueId id)
Set the sound data to play (specifying a Cue ID)
enum CriAtomExPlayerStatusTag CriAtomExPlayerStatus
Player status.
@ CRIATOMEXPLAYER_STATUS_PLAYEND
Definition: cri_le_atom_ex.h:3670



Even if thread_func1 and thread_func2 are invoked simultaneously in two threads, no problem occurs.

Exceptionally Thread-safe Functions

Even when the module itself is not thread-safe, following functions are exceptionally thread-safe.

These functions run without problem even when they are invoked simultaneously with other functions in the same module.

Notes on Releasing Resources

Functions which finalize the library ( the criAtomEx_Finalize function ) or destroy handles ( such as the criAtomExPlayer_Destroy function ) release all the library (handle) resources.
Therefore even if a thread-safe function is being executed, when these functions are invoked in other threads, serious problems, such as access violation, may occur.