Final Platform Layer  0.9.6-beta
Signals

Overview

This section explains how to create and manage Signals.
A Signal is a Kernel-Level object used to notify one or multiple waiting Threads.
It internally contains a Value which is either fplSignalValue_Set or fplSignalValue_Unset.
When this value gets changed, all Threads which waits on that Signal will wakeup.
They can be shared across process boundaries and may be used as standalone locks to shared data, but the number of Signals is limited by the OS that can be allocated at a time.

Initialize a Signal

Call fplSignalInit() with a pointer to fplSignalHandle as an argument, to initialize a Signal.
Also, you need to specify if the Signal starts as fplSignalValue_Set or fplSignalValue_Unset as a second argument.
When you are done with that Signal, you need to call fplSignalDestroy() to release its internal resources.

// Initialize a Signal as "unset"
// Error: Signal failed initializing -> Too many active Signals
}
// ... Signal is not required anymore

Waiting for Signal

Wait for a single Signal to be set

Call fplSignalWaitForOne() with a pointer to fplSignalHandle and a fplTimeoutValue argument, to let the current thread wait until the Signal is set.

// Wait until the Signal is set
// ... or
// Wait at max for 5 seconds or until the Signal is set
fplSignalWaitForOne(thread, 5000);

Wait for any Signal to be set

Call fplSignalWaitForAny() to let the current thread wait until at least one Signal is set.

Example, default signal handle array:

fplSignalHandle **signals; // Signals array already initialized
// Wait until one of the Signal is set
fplSignalWaitForAny(signals, numOfSignals, sizeof(fplSignalHandle *), FPL_TIMEOUT_INFINITE);
// ... or
// Wait at max for 5 seconds or until one of the Signal is set
fplSignalWaitForAny(signals, numOfSignals, sizeof(fplSignalHandle *), 5000);

Example, custom struct with stored signal handle:

typedef struct MyCustomStruct {
int a;
void *ptr;
fplSignalHandle *signal;
short b;
} MyCustomStruct;
MyCustomStruct *customSignals; // Struct array already initialized
fplSignalHandle *firstPointerToSignal = &customSignals[0].signal;
// Wait until one of the Signal is set
fplSignalWaitForAny(firstPointerToSignal, numOfSignals, sizeof(MyCustomStruct), FPL_TIMEOUT_INFINITE);
// ... or
// Wait at max for 5 seconds or until one of the Signal is set
fplSignalWaitForAny(firstPointerToSignal, numOfSignals, sizeof(MyCustomStruct), 5000);

Wait for all Signals to be set

Call fplSignalWaitForAll() to let the current thread wait until all Signals are set.

Example, default signal handle array:

fplSignalHandle **signals; // Signals array already initialized
// Wait until all of the Signals are set
fplSignalWaitForAll(signals, numOfSignals, sizeof(fplSignalHandle *), FPL_TIMEOUT_INFINITE);
// ... or
// Wait at max for 5 seconds or until all of the Signal are set
fplSignalWaitForAll(signals, numOfSignals, sizeof(fplSignalHandle *), 5000);

Example, custom struct with stored signal handle:

typedef struct MyCustomStruct {
int a;
void *ptr;
fplSignalHandle *signal;
short b;
} MyCustomStruct;
MyCustomStruct *customSignals; // Struct array already initialized
fplSignalHandle *firstPointerToSignal = &customSignals[0].signal;
// Wait until all of the Signals are set
fplSignalWaitForAll(firstPointerToSignal, numOfSignals, sizeof(MyCustomStruct), FPL_TIMEOUT_INFINITE);
// ... or
// Wait at max for 5 seconds or until all of the Signal are set
fplSignalWaitForAll(firstPointerToSignal, numOfSignals, sizeof(MyCustomStruct), 5000);

Setting a Signal

Call fplSignalSet() with a pointer to fplSignalHandle as an argument, to set a Signal and wakeup all waiting Threads.

Note
Unlike fplConditionVariable , setting a Signal is not Thread-Safe so you should ensure that only one thread at a time will set it!
// Use a mutex or another synchronization method to ensure that only one thread can set the Signal
fplMutexLock(&mutex);
fplSignalSet(signal);

Resetting a Signal

Call fplSignalReset() with a pointer to fplSignalHandle as an argument, to reset a Signal.

Note
Unlike fplConditionVariable , resetting a Signal is not Thread-Safe so you should ensure that only one thread at a time will set it!
// Use a mutex or another synchronization method to ensure that only one thread can reset the Signal
fplMutexLock(&mutex);
fplSignalDestroy
fpl_platform_api void fplSignalDestroy(fplSignalHandle *signal)
Releases the given signal and clears the structure to zero.
fplSignalHandle
The signal handle structure.
Definition: final_platform_layer.h:4564
fplSignalWaitForAll
fpl_platform_api bool fplSignalWaitForAll(fplSignalHandle **signals, const size_t count, const size_t stride, const fplTimeoutValue timeout)
Waits until all the given signals are waked up.
FPL_TIMEOUT_INFINITE
#define FPL_TIMEOUT_INFINITE
Infinite timeout constant.
Definition: final_platform_layer.h:4412
fplMutexUnlock
fpl_platform_api bool fplMutexUnlock(fplMutexHandle *mutex)
Unlocks the given mutex.
fplSignalInit
fpl_platform_api bool fplSignalInit(fplSignalHandle *signal, const fplSignalValue initialValue)
Initializes the given signal.
fplSignalWaitForAny
fpl_platform_api bool fplSignalWaitForAny(fplSignalHandle **signals, const size_t count, const size_t stride, const fplTimeoutValue timeout)
Waits until any of the given signals wakes up or the timeout has been reached.
fplSignalSet
fpl_platform_api bool fplSignalSet(fplSignalHandle *signal)
Sets the signal and wakes up the given signal.
fplMutexLock
fpl_platform_api bool fplMutexLock(fplMutexHandle *mutex)
Locks the given mutex and blocks any other threads.
fplSignalValue_Unset
Value is unset.
Definition: final_platform_layer.h:4574
fplSignalWaitForOne
fpl_platform_api bool fplSignalWaitForOne(fplSignalHandle *signal, const fplTimeoutValue timeout)
Waits until the given signal is waked up.
fplSignalReset
fpl_platform_api bool fplSignalReset(fplSignalHandle *signal)
Resets the signal.