QAtomic: pass explicit failure memory order to std::atomic::compare_exchange_strong

GCC 4.8 seems to get the failure memory order wrong when using the
overload that only accepts one memory order and produces errors such
as:

  bits/atomic_base.h:577:70: error: failure memory model cannot be stronger than success memory model for '__atomic_compare_exchange'
  return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2);
                                                                      ^
(as seen on Android).

Fix by explicitly passing the failure orders corresponding to the
success orders, as specified by the standard:

 relaxed → relaxed
 release → relaxed
 acquire → acquire
 acq_rel → acquire

(cf. http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange).

Task-number: QTBUG-59399
Change-Id: If046e735888cf331d2d6506d8d5ca9aa7402f9ad
Reviewed-by: David Faure <david.faure@kdab.com>
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Marc Mutz 2016-05-26 08:30:26 +02:00
parent 9ed389bf15
commit 5cc0de2e08

View File

@ -278,7 +278,7 @@ template <typename X> struct QAtomicOps
template <typename T>
static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed);
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
if (currentValue)
*currentValue = expectedValue;
return tmp;
@ -287,7 +287,7 @@ template <typename X> struct QAtomicOps
template <typename T>
static bool testAndSetAcquire(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire);
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire, std::memory_order_acquire);
if (currentValue)
*currentValue = expectedValue;
return tmp;
@ -296,7 +296,7 @@ template <typename X> struct QAtomicOps
template <typename T>
static bool testAndSetRelease(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release);
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release, std::memory_order_relaxed);
if (currentValue)
*currentValue = expectedValue;
return tmp;
@ -305,7 +305,7 @@ template <typename X> struct QAtomicOps
template <typename T>
static bool testAndSetOrdered(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW
{
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel);
bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel, std::memory_order_acquire);
if (currentValue)
*currentValue = expectedValue;
return tmp;