Add atomic adjust impl that uses GCC intrinsics. Also, make use of "constexpr" when available.
This commit is contained in:
parent
cea09d4b9e
commit
1be0fb5169
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "dtoolbase.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
|
||||
// Windows defines isnan() in a different place and with a different
|
||||
// name than everyone else. Sheesh.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -80,30 +80,38 @@ is_on(NotifySeverity severity) {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef NOTIFY_DEBUG
|
||||
template<class GetCategory>
|
||||
INLINE bool NotifyCategoryProxy<GetCategory>::
|
||||
is_spam() {
|
||||
#ifdef NOTIFY_DEBUG
|
||||
return get_unsafe_ptr()->is_spam();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
template<class GetCategory>
|
||||
CONSTEXPR bool NotifyCategoryProxy<GetCategory>::
|
||||
is_spam() {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NotifyCategoryProxy::is_debug
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef NOTIFY_DEBUG
|
||||
template<class GetCategory>
|
||||
INLINE bool NotifyCategoryProxy<GetCategory>::
|
||||
is_debug() {
|
||||
#ifdef NOTIFY_DEBUG
|
||||
return get_unsafe_ptr()->is_debug();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
template<class GetCategory>
|
||||
CONSTEXPR bool NotifyCategoryProxy<GetCategory>::
|
||||
is_debug() {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NotifyCategoryProxy::is_info
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue