Most functions are specified as signaling functions, which call the trap handler if a trap-enabled condition occurs. This behavior is not always desirable. For example, if temporary storage has been allocated and an error occurs, it is better to free the storage first and raise the condition at function exit. Another example is a threaded application where many functions use the same context simultaneously.
For each signaling function in the specification, libmpdec offers a quiet, thread-safe counterpart. The naming convention is such that if the signaling function is called mpd_add, the quiet function is called mpd_qadd.
All signaling functions are wrappers around quiet functions:
void mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status);
void
mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx)
{
uint32_t status = 0;
mpd_qmul(result, a, b, ctx, &status);
mpd_addstatus_raise(ctx, status);
}
Instead of writing to the context, mpd_qmul only updates the status parameter. mpd_addstatus_raise adds the accumulated status to the context and calls the trap handler if necessary.
For brevity’s sake, throughout this document only the quiet versions of functions will be explained.
All quiet functions except mpd_update_ln10, mpd_qln, mpd_qlog10 and mpd_qpow are thread-safe. The latter functions share the global variable mpd_ln10.
For the cdecimal module the situation is different. The GIL prevents that more than one of these functions is called simultaneously, so the module is thread-safe.