added some checks for compiler builtins.
enhanced SpinLock code
This commit is contained in:
@ -35,7 +35,7 @@
|
||||
#include <qse/macros.h>
|
||||
|
||||
#if (__cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1900) // C++11 or later
|
||||
#define QSE_CPP_CPP11 1
|
||||
#define QSE_LANG_CPP11 1
|
||||
|
||||
#define QSE_CPP_NOEXCEPT noexcept(true)
|
||||
#define QSE_CPP_EXPLICIT explicit
|
||||
@ -55,7 +55,7 @@
|
||||
|
||||
|
||||
#elif (__cplusplus >= 199711L) // C++98
|
||||
#undef QSE_CPP_CPP11
|
||||
#undef QSE_LANG_CPP11
|
||||
|
||||
#define QSE_CPP_NOEXCEPT throw()
|
||||
#define QSE_CPP_EXPLICIT
|
||||
|
@ -596,6 +596,9 @@
|
||||
/* Define to 1 if you have the `stat64' function. */
|
||||
#undef HAVE_STAT64
|
||||
|
||||
/* Define to 1 if you have the <stdatomic.h> header file. */
|
||||
#undef HAVE_STDATOMIC_H
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#undef HAVE_STDDEF_H
|
||||
|
||||
|
@ -508,6 +508,137 @@ static inline qse_uint32_t QSE_ROTR32 (qse_uint32_t v, int i)
|
||||
|
||||
|
||||
|
||||
/* =========================================================================
|
||||
* COMPILER FEATURE TEST MACROS
|
||||
* =========================================================================*/
|
||||
#if !defined(__has_builtin) && defined(_INTELC32_)
|
||||
/* intel c code builder 1.0 ended up with an error without this override */
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
#if !defined(__is_identifier)
|
||||
#define __is_identifier(x) 0
|
||||
#endif
|
||||
|
||||
#if !defined(__has_attribute)
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
||||
#if defined(__has_builtin)
|
||||
#if __has_builtin(__builtin_ctz)
|
||||
#define QSE_HAVE_BUILTIN_CTZ
|
||||
#endif
|
||||
#if __has_builtin(__builtin_ctzl)
|
||||
#define QSE_HAVE_BUILTIN_CTZL
|
||||
#endif
|
||||
#if __has_builtin(__builtin_ctzll)
|
||||
#define QSE_HAVE_BUILTIN_CTZLL
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_uadd_overflow)
|
||||
#define QSE_HAVE_BUILTIN_UADD_OVERFLOW
|
||||
#endif
|
||||
#if __has_builtin(__builtin_uaddl_overflow)
|
||||
#define QSE_HAVE_BUILTIN_UADDL_OVERFLOW
|
||||
#endif
|
||||
#if __has_builtin(__builtin_uaddll_overflow)
|
||||
#define QSE_HAVE_BUILTIN_UADDLL_OVERFLOW
|
||||
#endif
|
||||
#if __has_builtin(__builtin_umul_overflow)
|
||||
#define QSE_HAVE_BUILTIN_UMUL_OVERFLOW
|
||||
#endif
|
||||
#if __has_builtin(__builtin_umull_overflow)
|
||||
#define QSE_HAVE_BUILTIN_UMULL_OVERFLOW
|
||||
#endif
|
||||
#if __has_builtin(__builtin_umulll_overflow)
|
||||
#define QSE_HAVE_BUILTIN_UMULLL_OVERFLOW
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_sadd_overflow)
|
||||
#define QSE_HAVE_BUILTIN_SADD_OVERFLOW
|
||||
#endif
|
||||
#if __has_builtin(__builtin_saddl_overflow)
|
||||
#define QSE_HAVE_BUILTIN_SADDL_OVERFLOW
|
||||
#endif
|
||||
#if __has_builtin(__builtin_saddll_overflow)
|
||||
#define QSE_HAVE_BUILTIN_SADDLL_OVERFLOW
|
||||
#endif
|
||||
#if __has_builtin(__builtin_smul_overflow)
|
||||
#define QSE_HAVE_BUILTIN_SMUL_OVERFLOW
|
||||
#endif
|
||||
#if __has_builtin(__builtin_smull_overflow)
|
||||
#define QSE_HAVE_BUILTIN_SMULL_OVERFLOW
|
||||
#endif
|
||||
#if __has_builtin(__builtin_smulll_overflow)
|
||||
#define QSE_HAVE_BUILTIN_SMULLL_OVERFLOW
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_expect)
|
||||
#define QSE_HAVE_BUILTIN_EXPECT
|
||||
#endif
|
||||
|
||||
|
||||
#if __has_builtin(__sync_lock_test_and_set)
|
||||
#define QSE_HAVE_SYNC_LOCK_TEST_AND_SET
|
||||
#endif
|
||||
#if __has_builtin(__sync_lock_release)
|
||||
#define QSE_HAVE_SYNC_LOCK_RELEASE
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__sync_synchronize)
|
||||
#define QSE_HAVE_SYNC_SYNCHRONIZE
|
||||
#endif
|
||||
#if __has_builtin(__sync_bool_compare_and_swap)
|
||||
#define QSE_HAVE_SYNC_BOOL_COMPARE_AND_SWAP
|
||||
#endif
|
||||
#if __has_builtin(__sync_val_compare_and_swap)
|
||||
#define QSE_HAVE_SYNC_VAL_COMPARE_AND_SWAP
|
||||
#endif
|
||||
|
||||
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
|
||||
#if (__GNUC__ >= 4)
|
||||
#define QSE_HAVE_SYNC_LOCK_TEST_AND_SET
|
||||
#define QSE_HAVE_SYNC_LOCK_RELEASE
|
||||
|
||||
#define QSE_HAVE_SYNC_SYNCHRONIZE
|
||||
#define QSE_HAVE_SYNC_BOOL_COMPARE_AND_SWAP
|
||||
#define QSE_HAVE_SYNC_VAL_COMPARE_AND_SWAP
|
||||
#endif
|
||||
|
||||
#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
|
||||
#define QSE_HAVE_BUILTIN_CTZ
|
||||
#define QSE_HAVE_BUILTIN_EXPECT
|
||||
#endif
|
||||
|
||||
#if (__GNUC__ >= 5)
|
||||
#define QSE_HAVE_BUILTIN_UADD_OVERFLOW
|
||||
#define QSE_HAVE_BUILTIN_UADDL_OVERFLOW
|
||||
#define QSE_HAVE_BUILTIN_UADDLL_OVERFLOW
|
||||
#define QSE_HAVE_BUILTIN_UMUL_OVERFLOW
|
||||
#define QSE_HAVE_BUILTIN_UMULL_OVERFLOW
|
||||
#define QSE_HAVE_BUILTIN_UMULLL_OVERFLOW
|
||||
|
||||
#define QSE_HAVE_BUILTIN_SADD_OVERFLOW
|
||||
#define QSE_HAVE_BUILTIN_SADDL_OVERFLOW
|
||||
#define QSE_HAVE_BUILTIN_SADDLL_OVERFLOW
|
||||
#define QSE_HAVE_BUILTIN_SMUL_OVERFLOW
|
||||
#define QSE_HAVE_BUILTIN_SMULL_OVERFLOW
|
||||
#define QSE_HAVE_BUILTIN_SMULLL_OVERFLOW
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(QSE_HAVE_BUILTIN_EXPECT)
|
||||
# define QSE_LIKELY(x) (__builtin_expect(!!(x),1))
|
||||
# define QSE_UNLIKELY(x) (__builtin_expect(!!(x),0))
|
||||
#else
|
||||
# define QSE_LIKELY(x) (x)
|
||||
# define QSE_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* C++ NAMESPACE
|
||||
|
@ -30,40 +30,73 @@
|
||||
#include <qse/Types.hpp>
|
||||
#include <qse/Uncopyable.hpp>
|
||||
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
|
||||
// don't include anything
|
||||
#elif defined(QSE_LANG_CPP11)
|
||||
// NOTE: <stdatomic.h> in C11 doesn't seem compatible due to lack of
|
||||
// the keyword _Atomic in C++11
|
||||
# include <atomic>
|
||||
#endif
|
||||
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
|
||||
class SpinLock
|
||||
{
|
||||
public:
|
||||
SpinLock(): flag(0) {}
|
||||
|
||||
bool tryock()
|
||||
{
|
||||
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
|
||||
return !__sync_lock_test_and_set(&this->flag, 1);
|
||||
#elif defined(QSE_LANG_CPP11)
|
||||
return !this->flag.test_and_set();
|
||||
#else
|
||||
# error UNSUPPORTED
|
||||
#endif
|
||||
}
|
||||
|
||||
void lock ()
|
||||
{
|
||||
//while (!this->tryLock());
|
||||
while (__sync_lock_test_and_set(&this->flag, 1));
|
||||
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
|
||||
while (__sync_lock_test_and_set(&this->flag, 1)) { /* do nothing special */ }
|
||||
#elif defined(QSE_LANG_CPP11)
|
||||
while (flag.test_and_set()) { /* do nothing sepcial */ }
|
||||
#else
|
||||
# error UNSUPPORTED
|
||||
#endif
|
||||
}
|
||||
|
||||
void unlock ()
|
||||
{
|
||||
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
|
||||
__sync_lock_release (&this->flag);
|
||||
#elif defined(QSE_LANG_CPP11)
|
||||
flag.clear ();
|
||||
#else
|
||||
# error UNSUPPORTED
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
|
||||
volatile int flag;
|
||||
#elif defined(QSE_LANG_CPP11)
|
||||
std::atomic_flag flag;
|
||||
#else
|
||||
# error UNSUPPORTED;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ScopedSpinLock: public Uncopyable
|
||||
class ScopedSpinLocker: public Uncopyable
|
||||
{
|
||||
ScopedSpinLock (SpinLock& spl): spl(spl)
|
||||
public:
|
||||
ScopedSpinLocker (SpinLock& spl): spl(spl)
|
||||
{
|
||||
this->spl.lock ();
|
||||
}
|
||||
|
||||
~ScopedSpinLock ()
|
||||
~ScopedSpinLocker ()
|
||||
{
|
||||
this->spl.unlock ();
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ protected:
|
||||
F __lfunc;
|
||||
};
|
||||
|
||||
#if defined(QSE_CPP_CPP11)
|
||||
#if defined(QSE_LANG_CPP11)
|
||||
|
||||
|
||||
#if 0
|
||||
@ -219,7 +219,7 @@ protected:
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // QSE_CPP_CPP11
|
||||
#endif // QSE_LANG_CPP11
|
||||
|
||||
|
||||
QSE_END_NAMESPACE(QSE)
|
||||
|
@ -52,6 +52,11 @@
|
||||
# error Unsupported operating system
|
||||
#endif
|
||||
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
||||
# define QSE_LANG_C11
|
||||
#else
|
||||
# undef QSE_LANG_C11
|
||||
#endif
|
||||
|
||||
#if defined(EMSCRIPTEN)
|
||||
# if defined(QSE_SIZEOF___INT128)
|
||||
@ -537,12 +542,17 @@ typedef int qse_mcint_t;
|
||||
* #QSE_WCHAR_EOF.
|
||||
*/
|
||||
|
||||
#if defined(QSE_WCHAR_PREFER_CHAR16) && defined(__GNUC__) && defined(__CHAR16_TYPE__) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
||||
#if defined(QSE_WCHAR_PREFER_CHAR16) && defined(__GNUC__) && defined(__CHAR16_TYPE__)
|
||||
/* C11 */
|
||||
#if defined(__cplusplus)
|
||||
typedef char16_t qse_wchar_t;
|
||||
#else
|
||||
/* i don't want to include <uchar.h> */
|
||||
typedef __CHAR16_TYPE__ qse_wchar_t;
|
||||
#endif
|
||||
typedef qse_uint16_t qse_wchau_t;
|
||||
|
||||
|
||||
|
||||
#if (QSE_SIZEOF_INT > 2)
|
||||
typedef int qse_wcint_t;
|
||||
#else
|
||||
|
Reference in New Issue
Block a user