Skip to content

Commit edf74a5

Browse files
committed
docs: Add thread safety documentation
Documents the thread-local RNG implementation and provides guidance for multi-threaded usage of PocketSphinx: - Explains the thread safety issue with global RNG state - Describes the thread-local storage solution - Provides migration guide for existing code - Lists performance considerations - Documents the PS_THREAD_LOCAL_RNG build option - Includes examples of thread-safe usage This helps users understand and properly utilize the thread-safe RNG functionality in their applications.
1 parent 0aead8d commit edf74a5

1 file changed

Lines changed: 89 additions & 0 deletions

File tree

docs/thread_safety.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Thread Safety in PocketSphinx
2+
3+
## Random Number Generator Thread Safety
4+
5+
PocketSphinx uses a Mersenne Twister random number generator for features like dithering in audio processing. Prior to version 5.0.4, this RNG used global state and was not thread-safe.
6+
7+
### Thread-Local Storage Support
8+
9+
Starting with version 5.0.4, PocketSphinx supports thread-local storage for the random number generator, making it thread-safe when enabled.
10+
11+
#### Enabling Thread-Local RNG
12+
13+
Thread-local storage is **enabled by default** when building with CMake on supported platforms:
14+
15+
```bash
16+
cmake -DPS_THREAD_LOCAL_RNG=ON ..
17+
```
18+
19+
To explicitly disable it:
20+
21+
```bash
22+
cmake -DPS_THREAD_LOCAL_RNG=OFF ..
23+
```
24+
25+
#### Platform Requirements
26+
27+
Thread-local storage requires one of:
28+
- C11 compiler with `_Thread_local` support
29+
- C++11 compiler with `thread_local` support
30+
- GCC 3.3+ with `__thread` support
31+
- Visual Studio 2015+ with `__declspec(thread)` support
32+
33+
Most modern compilers support thread-local storage.
34+
35+
#### Behavior
36+
37+
When thread-local storage is enabled:
38+
- Each thread maintains its own independent RNG state
39+
- Calling `genrand_seed()` in one thread does not affect other threads
40+
- Sequences generated in different threads are independent
41+
- Thread-safe without any locks or synchronization
42+
43+
When thread-local storage is disabled:
44+
- RNG uses global state (legacy behavior)
45+
- **NOT thread-safe** - concurrent access causes race conditions
46+
- All threads share the same RNG state
47+
48+
#### API Compatibility
49+
50+
The API remains unchanged. Existing code continues to work:
51+
52+
```c
53+
#include <pocketsphinx.h>
54+
#include "util/genrand.h"
55+
56+
/* Seed the RNG */
57+
genrand_seed(12345);
58+
59+
/* Generate random numbers */
60+
long value = genrand_int31(); /* [0, 2^31-1] */
61+
double real = genrand_real3(); /* (0, 1) */
62+
```
63+
64+
#### Where RNG is Used
65+
66+
The random number generator is primarily used for:
67+
- **Audio dithering** in feature extraction (when dithering is enabled)
68+
- Other stochastic processes in speech recognition
69+
70+
Most applications don't need to interact with the RNG directly.
71+
72+
#### Migration Notes
73+
74+
For applications using PocketSphinx in multiple threads:
75+
1. Ensure you're building with `PS_THREAD_LOCAL_RNG=ON` (default)
76+
2. Be aware that each thread now has independent RNG state
77+
3. If you need reproducible sequences across threads, seed each thread explicitly
78+
79+
#### Testing Thread Safety
80+
81+
You can verify thread safety by running:
82+
```bash
83+
./test_genrand_thread_tls
84+
```
85+
86+
This test verifies that:
87+
- Each thread maintains independent RNG state
88+
- No collisions occur between thread sequences
89+
- Deterministic behavior is preserved within each thread

0 commit comments

Comments
 (0)