diff --git a/src/erfadatextra.c b/src/erfadatextra.c index f70400c..c58f7ed 100644 --- a/src/erfadatextra.c +++ b/src/erfadatextra.c @@ -17,9 +17,10 @@ */ #include "erfa.h" #include "erfaextra.h" +#include "erfadatextra.h" -static eraLEAPSECOND *changes; -static int NDAT = -1; +static ERFA_THREAD_LOCAL eraLEAPSECOND *changes; +static ERFA_THREAD_LOCAL int NDAT = -1; int eraGetLeapSeconds(eraLEAPSECOND **leapseconds) diff --git a/src/erfadatextra.h b/src/erfadatextra.h index afea18b..7bf4626 100644 --- a/src/erfadatextra.h +++ b/src/erfadatextra.h @@ -23,4 +23,30 @@ int eraDatini(const eraLEAPSECOND *builtin, int n_builtin, eraLEAPSECOND **leapseconds); +/* +** For thread safety we want a way to define thread-local variables. +** If no TLS is available, fall back to ordinary storage and disable +** thread safety for those variables. This mostly follows the numpy +** specification (as of 8203da6e4cdad722664fa740c7a9514104483f07) +** +** The order is: +** C++ >= 11 and GCC C >= 23 uses thread_local +** GCC: 11 <= C < 23 uses _Thread_local +** Clang uses __thread +** MSVC uses _declspec(thread) +*/ +#if defined(__cplusplus) && __cplusplus >= 201103L +# define ERFA_THREAD_LOCAL thread_local +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +# define ERFA_THREAD_LOCAL thread_local +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +# define ERFA_THREAD_LOCAL _Thread_local +#elif defined(__GNUC__) || defined(__clang__) +# define ERFA_THREAD_LOCAL __thread +#elif defined(_MSC_VER) +# define ERFA_THREAD_LOCAL __declspec(thread) +#else +# define ERFA_THREAD_LOCAL +#endif + #endif