From 096df4242a1062904369a417449c1d12fe40f507 Mon Sep 17 00:00:00 2001 From: Naman Dixit Date: Sat, 6 Jun 2020 15:11:09 +0530 Subject: [PATCH] Proper cross-platform thread_local and alignas --- settings.h | 74 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/settings.h b/settings.h index 695ebfb7..3bb77264 100644 --- a/settings.h +++ b/settings.h @@ -10,20 +10,74 @@ do not use this unless you are certain your application won't use SSE */ /* #define LIBCO_NO_SSE */ -#if defined(LIBCO_C) - #if defined(LIBCO_MP) - #define thread_local __thread - #else +#if !defined(thread_local) // User can override thread_local for obscure compilers + #if !defined(LIBCO_MP) // Running in single-threaded environment #define thread_local + #else // Running in multi-threaded environment + #if defined(__STDC_VERSION__) // Compiling as C Language + #if defined(_MSC_VER) // Don't rely on MSVC's C11 support + #define thread_local __declspec(thread) + #elif __STDC_VERSION__ < 201112L // If we are on C90/99 + #if defined(__clang__) || defined(__GNUC__) // Clang and GCC + #define thread_local __thread + #else // Otherwise, we ignore the directive (unless user provides their own) + #define thread_local + #endif + #else // C11 and newer define thread_local in threads.h + #include + #endif + #elif defined(__cplusplus) // Compiling as C++ Language + #if __cplusplus < 201103L // thread_local is a C++11 feature + #if defined(_MSC_VER) + #define thread_local __declspec(thread) + #elif defined(__clang__) || defined(__GNUC__) + #define thread_local __thread + #else // Otherwise, we ignore the directive (unless user provides their own) + #define thread_local + #endif + #else // In C++ >= 11, thread_local in a builtin keyword + // Don't do anything + #endif + #endif #endif #endif -#if __STDC_VERSION__ >= 201112L - #if !defined(_MSC_VER) - #include - #endif -#else - #define alignas(bytes) +/* In alignas(a), 'a' should be a power of two that is at least the type's + alignment and at most the implementation's alignment limit. This limit is + 2**13 on MSVC. To be portable to MSVC through at least version 10.0, + 'a' should be an integer constant, as MSVC does not support expressions + such as 1 << 3. + + The following C11 requirements are NOT supported on MSVC: + + - If 'a' is zero, alignas has no effect. + - alignas can be used multiple times; the strictest one wins. + - alignas (TYPE) is equivalent to alignas (alignof (TYPE)). +*/ +#if !defined(alignas) + #if defined(__STDC_VERSION__) // C Language + #if defined(_MSC_VER) // Don't rely on MSVC's C11 support + #define alignas(bytes) __declspec(align(bytes)) + #elif __STDC_VERSION__ >= 201112L // C11 and above + #include + #elif defined(__clang__) || defined(__GNUC__) // C90/99 on Clang/GCC + #define alignas(bytes) __attribute__ ((aligned (bytes))) + #else // Otherwise, we ignore the directive (user should provide their own) + #define alignas(bytes) + #endif + #elif defined(__cplusplus) // C++ Language + #if __cplusplus < 201103L + #if defined(_MSC_VER) + #define alignas(bytes) __declspec(align(bytes)) + #elif defined(__clang__) || defined(__GNUC__) // C++98/03 on Clang/GCC + #define alignas(bytes) __attribute__ ((aligned (bytes))) + #else // Otherwise, we ignore the directive (unless user provides their own) + #define alignas(bytes) + #endif + #else // C++ >= 11 has alignas keyword + // Do nothing + #endif + #endif // = !defined(__STDC_VERSION__) && !defined(__cplusplus) #endif #if !defined(LIBCO_ASSERT)