QFutureInterface: use (new) qYieldCpu() instead of _mm_pause()

This loop here was a lonesome instance of a CAS loop in which adding
_mm_pause() was simple, because the code didn't use the usual pattern

  do {
     construct new value
  } while (!testAndSet)

we use everywhere else in Qt.

In search of an elegant pattern that would allow to apply
qYieldCpu()/_mm_pause() to those idiomatic CAS loops, too, I've
reached for a lambda to construct the new value. This should apply to
all (tight) CAS loops, and may form the basis of an API extension
whereby we take that lambda as a function argument to encapsulate the
CAS loop in an algorithm (a function).

Pick-to: 6.3
Change-Id: Id4a8f174dd812aa26f0b163e943bd4558e5e6a7b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2022-04-30 10:21:26 +02:00
parent 1808df9ce5
commit c847f0091d

View File

@ -43,12 +43,9 @@
#include <QtCore/qatomic.h>
#include <QtCore/qthread.h>
#include <QtCore/private/qsimd_p.h> // for qYieldCpu()
#include <private/qthreadpool_p.h>
#ifdef Q_PROCESSOR_X86
# include <immintrin.h> // for _mm_pause()
#endif
#ifdef interface
# undef interface
#endif
@ -108,17 +105,11 @@ static inline int switch_off(QAtomicInt &a, int which)
static inline int switch_from_to(QAtomicInt &a, int from, int to)
{
int newValue;
int expected = a.loadRelaxed();
for (;;) {
newValue = (expected & ~from) | to;
if (a.testAndSetRelaxed(expected, newValue, expected))
break;
#ifdef Q_PROCESSOR_X86
_mm_pause();
#endif
}
return newValue;
const auto adjusted = [&](int old) { return (old & ~from) | to; };
int value = a.loadRelaxed();
while (!a.testAndSetRelaxed(value, adjusted(value), value))
qYieldCpu();
return value;
}
void QFutureInterfaceBase::cancel()