The SDDS libraries support concurrent use by multiple threads when each thread uses separate library objects and caller-owned buffers. In particular, independent SDDS_DATASET structures may be read, written, queried, and terminated concurrently. A single SDDS_DATASET structure is not locked as one object; callers must serialize operations if more than one thread accesses the same dataset handle.
The SDDS error stack is thread-local. Calls such as SDDS_SetError, SDDS_SetError0, SDDS_NumberOfErrors, SDDS_GetErrorMessages, SDDS_PrintErrors, and SDDS_ClearErrors operate on the calling thread’s error history.
Several process-global settings are protected by internal locks, including SDDS_SetDefaultIOBufferSize, SDDS_SetRowLimit, SDDS_SetTerminateMode, SDDS_SetNameValidityFlags, SDDS_SetAutoCheckMode, and SDDS_RegisterProgramName. These calls are protected against data races, but the settings remain process-global. For deterministic behavior, applications should set them before creating worker threads or provide their own synchronization around changes.
The RPN library has per-thread execution stacks, so ordinary rpn calls do not share numeric, logical, string, or integer stack contents between threads. RPN definitions, memories, and arrays remain process-global and are serialized by the recursive rpn_lock/rpn_unlock API. Callers that retain a pointer returned by rpn_getarraypointer while other threads may mutate RPN arrays should hold rpn_lock until the pointer is no longer in use.
The supporting utility and math libraries use thread-local storage or internal locks for formerly shared scratch buffers, flags, random-number state, error state, and work arrays. This includes mdblib, mdbcommon, mdbmth, namelist, matlib, fftpack, meschach, CSA, natural-neighbor interpolation, and xlslib. These protections do not make concurrent mutation of the same caller-owned matrix, interpolation object, file stream, or output buffer safe without caller synchronization.
Normal builds require compiler support for thread-local storage and an atomic or platform lock primitive. Defining SDDS_UNSAFE_NO_THREADS disables these protections and should be used only for explicit single-thread builds.