diff --git a/dtool/src/dtoolbase/atomicAdjust.h b/dtool/src/dtoolbase/atomicAdjust.h index 1bd24d22ea..6ce85c3589 100644 --- a/dtool/src/dtoolbase/atomicAdjust.h +++ b/dtool/src/dtoolbase/atomicAdjust.h @@ -23,7 +23,7 @@ #include "atomicAdjustDummyImpl.h" typedef AtomicAdjustDummyImpl AtomicAdjust; -#elif defined(__i386__) || defined(_M_IX86) +#elif defined(__i386__) || defined(_M_IX86) // For an i386 architecture, we'll always use the i386 implementation. // It should be safe for any OS, and it might be a bit faster than // any OS-provided calls. @@ -39,6 +39,15 @@ typedef AtomicAdjustI386Impl AtomicAdjust; #define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1 #define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1 +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) +// GCC 4.7 and above has built-in __atomic functions for atomic operations. + +#include "atomicAdjustGccImpl.h" +typedef AtomicAdjustGccImpl AtomicAdjust; + +#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1 +#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1 + #elif defined(THREAD_WIN32_IMPL) #include "atomicAdjustWin32Impl.h" diff --git a/dtool/src/dtoolbase/atomicAdjustGccImpl.I b/dtool/src/dtoolbase/atomicAdjustGccImpl.I new file mode 100644 index 0000000000..6831a16a1e --- /dev/null +++ b/dtool/src/dtoolbase/atomicAdjustGccImpl.I @@ -0,0 +1,148 @@ +// Filename: atomicAdjustGccImpl.I +// Created by: rdb (04Jul14) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::inc +// Access: Public, Static +// Description: Atomically increments the indicated variable. +//////////////////////////////////////////////////////////////////// +INLINE void AtomicAdjustGccImpl:: +inc(TVOLATILE AtomicAdjustGccImpl::Integer &var) { + __atomic_fetch_add(&var, 1, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::dec +// Access: Public, Static +// Description: Atomically decrements the indicated variable and +// returns true if the new value is nonzero, false if it +// is zero. +//////////////////////////////////////////////////////////////////// +INLINE bool AtomicAdjustGccImpl:: +dec(TVOLATILE AtomicAdjustGccImpl::Integer &var) { + return (__atomic_sub_fetch(&var, 1, __ATOMIC_SEQ_CST) != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::add +// Access: Public, Static +// Description: Atomically computes var += delta. It is legal for +// delta to be negative. +//////////////////////////////////////////////////////////////////// +INLINE void AtomicAdjustGccImpl:: +add(TVOLATILE AtomicAdjustGccImpl::Integer &var, + AtomicAdjustGccImpl::Integer delta) { + __atomic_fetch_add(&var, delta, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::set +// Access: Public, Static +// Description: Atomically changes the indicated variable and +// returns the original value. +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Integer AtomicAdjustGccImpl:: +set(TVOLATILE AtomicAdjustGccImpl::Integer &var, + AtomicAdjustGccImpl::Integer new_value) { + + return __atomic_exchange_n(&var, new_value, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::get +// Access: Public, Static +// Description: Atomically retrieves the snapshot value of the +// indicated variable. This is the only guaranteed safe +// way to retrieve the value that other threads might be +// asynchronously setting, incrementing, or decrementing +// (via other AtomicAjust methods). +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Integer AtomicAdjustGccImpl:: +get(const TVOLATILE AtomicAdjustGccImpl::Integer &var) { + return __atomic_load_n(&var, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::set_ptr +// Access: Public, Static +// Description: Atomically changes the indicated variable and +// returns the original value. +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Pointer AtomicAdjustGccImpl:: +set_ptr(TVOLATILE AtomicAdjustGccImpl::Pointer &var, + AtomicAdjustGccImpl::Pointer new_value) { + + return __atomic_exchange_n(&var, new_value, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::get_ptr +// Access: Public, Static +// Description: Atomically retrieves the snapshot value of the +// indicated variable. This is the only guaranteed safe +// way to retrieve the value that other threads might be +// asynchronously setting, incrementing, or decrementing +// (via other AtomicAjust methods). +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Pointer AtomicAdjustGccImpl:: +get_ptr(const TVOLATILE AtomicAdjustGccImpl::Pointer &var) { + return __atomic_load_n(&var, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::compare_and_exchange +// Access: Public, Static +// Description: Atomic compare and exchange. +// +// If mem is equal to old_value, store new_value in mem. +// In either case, return the original value of mem. +// The caller can test for success by comparing +// return_value == old_value. +// +// The atomic function expressed in pseudo-code: +// +// orig_value = mem; +// if (mem == old_value) { +// mem = new_value; +// } +// return orig_value; +// +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Integer AtomicAdjustGccImpl:: +compare_and_exchange(TVOLATILE AtomicAdjustGccImpl::Integer &mem, + AtomicAdjustGccImpl::Integer old_value, + AtomicAdjustGccImpl::Integer new_value) { + + __atomic_compare_exchange_n(&mem, &old_value, new_value, false, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return old_value; +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::compare_and_exchange_ptr +// Access: Public, Static +// Description: Atomic compare and exchange. +// +// As above, but works on pointers instead of integers. +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Pointer AtomicAdjustGccImpl:: +compare_and_exchange_ptr(TVOLATILE AtomicAdjustGccImpl::Pointer &mem, + AtomicAdjustGccImpl::Pointer old_value, + AtomicAdjustGccImpl::Pointer new_value) { + + __atomic_compare_exchange_n(&mem, &old_value, new_value, false, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return old_value; +} diff --git a/dtool/src/dtoolbase/atomicAdjustGccImpl.h b/dtool/src/dtoolbase/atomicAdjustGccImpl.h new file mode 100644 index 0000000000..2c8003948d --- /dev/null +++ b/dtool/src/dtoolbase/atomicAdjustGccImpl.h @@ -0,0 +1,60 @@ +// Filename: atomicAdjustGccImpl.h +// Created by: rdb (04Jul14) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef ATOMICADJUSTGCCIMPL_H +#define ATOMICADJUSTGCCIMPL_H + +#include "dtoolbase.h" +#include "selectThreadImpl.h" + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) + +//////////////////////////////////////////////////////////////////// +// Class : AtomicAdjustGccImpl +// Description : Uses GCC built-ins to implement atomic adjustments. +//////////////////////////////////////////////////////////////////// +class EXPCL_DTOOL AtomicAdjustGccImpl { +public: +#if __GCC_ATOMIC_LONG_LOCK_FREE > __GCC_ATOMIC_INT_LOCK_FREE + // If the long can be more lock-free than int, use it instead. + typedef __attribute__ ((aligned (__SIZEOF_LONG__))) long Integer; +#else + typedef __attribute__ ((aligned (__SIZEOF_INT__))) int Integer; +#endif + typedef void *UnalignedPointer; + typedef __attribute__ ((aligned (__SIZEOF_POINTER__))) UnalignedPointer Pointer; + + INLINE static void inc(TVOLATILE Integer &var); + INLINE static bool dec(TVOLATILE Integer &var); + INLINE static void add(TVOLATILE Integer &var, Integer delta); + INLINE static Integer set(TVOLATILE Integer &var, Integer new_value); + INLINE static Integer get(const TVOLATILE Integer &var); + + INLINE static Pointer set_ptr(TVOLATILE Pointer &var, Pointer new_value); + INLINE static Pointer get_ptr(const TVOLATILE Pointer &var); + + INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem, + Integer old_value, + Integer new_value); + + INLINE static Pointer compare_and_exchange_ptr(TVOLATILE Pointer &mem, + Pointer old_value, + Pointer new_value); +}; + +#include "atomicAdjustGccImpl.I" + +#endif // HAVE_POSIX_THREADS + +#endif diff --git a/dtool/src/dtoolbase/cmath.I b/dtool/src/dtoolbase/cmath.I index f1b7940c90..8b975bf924 100644 --- a/dtool/src/dtoolbase/cmath.I +++ b/dtool/src/dtoolbase/cmath.I @@ -365,7 +365,7 @@ cpow(int x, int y) { INLINE bool cnan(double v) { #ifndef _WIN32 - return (isnan(v) != 0); + return (std::isnan(v) != 0); #else return (_isnan(v) != 0); #endif diff --git a/dtool/src/dtoolbase/cmath.h b/dtool/src/dtoolbase/cmath.h index 4812b2a891..d4494f81ca 100644 --- a/dtool/src/dtoolbase/cmath.h +++ b/dtool/src/dtoolbase/cmath.h @@ -23,7 +23,7 @@ #include "dtoolbase.h" -#include +#include // Windows defines isnan() in a different place and with a different // name than everyone else. Sheesh. diff --git a/dtool/src/dtoolbase/dtoolbase_cc.h b/dtool/src/dtoolbase/dtoolbase_cc.h index ad9e9897dd..0829d4ad7d 100644 --- a/dtool/src/dtoolbase/dtoolbase_cc.h +++ b/dtool/src/dtoolbase/dtoolbase_cc.h @@ -33,6 +33,7 @@ using namespace std; #define INLINE inline #define TYPENAME typename +#define CONSTEXPR #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname) @@ -119,6 +120,16 @@ typedef ios::seekdir ios_seekdir; #define INLINE inline #endif +#if defined(__has_extension) // Clang magic. +#if __has_extension(cxx_constexpr) +#define CONSTEXPR constexpr +#endif +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define CONSTEXPR constexpr +#else +#define CONSTEXPR INLINE +#endif + #if defined(WIN32_VC) && !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES) // This macro must be used to export an instantiated template class // from a DLL. If the template class name itself contains commas, it diff --git a/dtool/src/prc/notifyCategory.I b/dtool/src/prc/notifyCategory.I index 7a47e85926..579c492e93 100644 --- a/dtool/src/prc/notifyCategory.I +++ b/dtool/src/prc/notifyCategory.I @@ -106,7 +106,7 @@ is_debug() const { // methods are redefined to be static to make it more // obvious to the compiler. //////////////////////////////////////////////////////////////////// -INLINE bool NotifyCategory:: +CONSTEXPR bool NotifyCategory:: is_spam() { return false; } @@ -119,7 +119,7 @@ is_spam() { // methods are redefined to be static to make it more // obvious to the compiler. //////////////////////////////////////////////////////////////////// -INLINE bool NotifyCategory:: +CONSTEXPR bool NotifyCategory:: is_debug() { return false; } diff --git a/dtool/src/prc/notifyCategory.h b/dtool/src/prc/notifyCategory.h index ff7b366bd2..30539ec3b8 100644 --- a/dtool/src/prc/notifyCategory.h +++ b/dtool/src/prc/notifyCategory.h @@ -56,8 +56,8 @@ PUBLISHED: INLINE bool is_spam() const; INLINE bool is_debug() const; #else - INLINE static bool is_spam(); - INLINE static bool is_debug(); + CONSTEXPR static bool is_spam(); + CONSTEXPR static bool is_debug(); #endif INLINE bool is_info() const; INLINE bool is_warning() const; diff --git a/dtool/src/prc/notifyCategoryProxy.I b/dtool/src/prc/notifyCategoryProxy.I index 2dff5ce76d..10b956f763 100644 --- a/dtool/src/prc/notifyCategoryProxy.I +++ b/dtool/src/prc/notifyCategoryProxy.I @@ -80,30 +80,38 @@ is_on(NotifySeverity severity) { // Access: Public // Description: //////////////////////////////////////////////////////////////////// +#ifdef NOTIFY_DEBUG template INLINE bool NotifyCategoryProxy:: is_spam() { -#ifdef NOTIFY_DEBUG return get_unsafe_ptr()->is_spam(); -#else - return false; -#endif } +#else +template +CONSTEXPR bool NotifyCategoryProxy:: +is_spam() { + return false; +} +#endif //////////////////////////////////////////////////////////////////// // Function: NotifyCategoryProxy::is_debug // Access: Public // Description: //////////////////////////////////////////////////////////////////// +#ifdef NOTIFY_DEBUG template INLINE bool NotifyCategoryProxy:: is_debug() { -#ifdef NOTIFY_DEBUG return get_unsafe_ptr()->is_debug(); -#else - return false; -#endif } +#else +template +CONSTEXPR bool NotifyCategoryProxy:: +is_debug() { + return false; +} +#endif //////////////////////////////////////////////////////////////////// // Function: NotifyCategoryProxy::is_info diff --git a/dtool/src/prc/notifyCategoryProxy.h b/dtool/src/prc/notifyCategoryProxy.h index 37b9383c00..5a306497cd 100644 --- a/dtool/src/prc/notifyCategoryProxy.h +++ b/dtool/src/prc/notifyCategoryProxy.h @@ -85,8 +85,8 @@ public: INLINE bool is_spam(); INLINE bool is_debug(); #else - INLINE static bool is_spam(); - INLINE static bool is_debug(); + CONSTEXPR static bool is_spam(); + CONSTEXPR static bool is_debug(); #endif INLINE bool is_info(); INLINE bool is_warning();