-
Notifications
You must be signed in to change notification settings - Fork 13
Synchronization methods
When multiple Threads access the same data, reads and writes can interleave in any order.
Without synchronization the result is a race condition: lost updates, torn reads, or inconsistent state.
Even a single statement like counter++ is not atomic - it is a load, an add and a store.
Two threads running it in parallel can both read the same value, add one, and write back the same result - losing one increment.
Synchronization primitives serialize access to shared data or signal state changes between Threads, so the program behaves as intended.
Use a fplMutexHandle to ensure only one Thread executes a code section at a time.
static counterMutex;
static uint32_t sharedCounter;
void IncrementCounter() {
(&counterMutex);
++sharedCounter; // safe: only one Thread at a time
(&counterMutex);
}Use a fplSignalHandle when one Thread must tell others that something happened (e.g. work is ready).
static workReady;
void ProducerThread() {
// ... produce work ...
(&workReady); // wake all waiters
}
void ConsumerThread() {
(&workReady, );
// ... consume work ...
}Use a fplConditionVariable together with a fplMutexHandle when waiters must check a condition under a lock and re-check after wakeup.
static queueMutex;
static queueCond;
static int itemCount;
void Push() {
(&queueMutex);
++itemCount;
(&queueCond); // wake one waiter
(&queueMutex);
}
void Pop() {
(&queueMutex);
while (itemCount == 0) { // re-check after wakeup
(&queueCond, &queueMutex, );
}
--itemCount;
(&queueMutex);
}Use a fplSemaphoreHandle to allow up to N Threads into a section at the same time.
static pool; // init with N permits
void UseResource() {
(&pool, ); // take a permit
// ... use one of N shared resources ...
(&pool); // give it back
}Use atomics when only a single integer or pointer needs to be updated safely, without a Mutex.
static volatile uint32_t counter;
void IncrementCounter() {
(&counter, 1); // safe without a lock
}| Primitive | Purpose | Scope | Cost | Notes |
|---|---|---|---|---|
| fplMutexHandle | Mutual exclusion of a code section | Same process | Low | Only the owner Thread can unlock |
| fplSignalHandle | Notify one or many waiters | Cross-process | Medium | Set/Reset is not Thread-Safe by itself |
| fplConditionVariable | Wait for a predicate under a Mutex | Same process | Medium | Requires a Mutex; supports signal and broadcast |
| fplSemaphoreHandle | Limit N concurrent accessors | Same process | Medium | Any Thread can release; counted permits |
| Atomics | Lock-free op on a single value | Same process | Lowest | One variable at a time; includes a memory barrier |
Note: Pick the lightest primitive that fits the problem. Atomics for a single value, a Mutex for a small critical section, a Condition-Variable when waiting on a predicate, a Semaphore for bounded resources, a Signal for cross-process or fan-out notifications.
- Assertion & Debug
- Atomic operations
- Audio functions
- Clipboard functions
- Console functions
- Constants
- Display/Monitor functions
- Dynamic library loading
- Error Handling
- Files/IO functions
- Function macros
- Hardware Infos
- Input types and functions
- Localization functions
- Logging
- Memory Macros
- Memory functions
- Operating system Infos
- Path functions
- Platform functions
- Session Infos
- Settings & Configurations
- Storage class identifiers
- String functions
- Threading and synchronizations routines
- Timing functions
- Video functions
- Window events
- Window functions
- fplARMCPUCapabilities
- fplAudioChannelMap
- fplAudioDeviceID
- fplAudioDeviceInfo
- fplAudioFormat
- fplAudioSettings
- fplColor32
- fplConditionVariable
- fplConsoleSettings
- fplCPUCapabilities
- fplCPUIDLeaf
- fplDateTime
- fplDateTimeCreationResult
- fplDateTimeResult
- fplDisplayInfo
- fplDisplayMode
- fplDynamicLibraryHandle
- fplEndianess
- fplEvent
- fplFileEntry
- fplFileHandle
- fplFilePermissions
- fplFileTimeStamps
- fplGamepadButton
- fplGamepadData
- fplGamepadEvent
- fplGamepadInfo
- fplGamepadInputBinding
- fplGamepadMapping
- fplGamepadSettings
- fplGamepadState
- fplGamepadStates
- fplGraphicsApiSettings
- fplImageSource
- fplInputBackendMask
- fplInputBackendSupport
- fplInputDevice
- fplInputDeviceGuid
- fplInputSettings
- fplInternalConditionVariable
- fplInternalDynamicLibraryHandle
- fplInternalFileEntryHandle
- fplInternalFileHandle
- fplInternalFileRootInfo
- fplInternalMutexHandle
- fplInternalSemaphoreHandle
- fplInternalSignalHandle
- fplInternalThreadHandle
- fplKeyboardEvent
- fplKeyboardState
- fplLogSettings
- fplLogWriter
- fplLogWriterConsole
- fplLogWriterCustom
- fplMemoryAllocationSettings
- fplMemoryBlock
- fplMemoryInfos
- fplMemorySettings
- fplMouseEvent
- fplMouseState
- fplMutexHandle
- fplOpenGLSettings
- fplOSVersionInfos
- fplSemaphoreHandle
- fplSettings
- fplSignalHandle
- fplSpecificAudioSettings
- fplThreadHandle
- fplThreadParameters
- fplTimestamp
- fplVersionInfo
- fplVideoBackBuffer
- fplVideoRect
- fplVideoRequirements
- fplVideoRequirementsVulkan
- fplVideoSettings
- fplVideoSurface
- fplVideoSurfaceOpenGL
- fplVideoSurfaceVulkan
- fplVideoWindow
- fplVulkanSettings
- fplWindowCallbacks
- fplWindowDropFiles
- fplWindowEvent
- fplWindowPosition
- fplWindowSettings
- fplWindowSize
- fplX86CPUCapabilities