diff options
author | Marc Mutz <marc.mutz@qt.io> | 2022-04-30 10:21:26 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2022-04-30 23:54:38 +0200 |
commit | c847f0091d484de7b3fb1049838eee3f2ac3dfc5 (patch) | |
tree | d3837330a68e4e17bbb974c3219deda61308dcb0 /src/corelib/thread/qfutureinterface.cpp | |
parent | 1808df9ce59a8c1d426f0361e25120a7852a6442 (diff) |
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>
Diffstat (limited to 'src/corelib/thread/qfutureinterface.cpp')
-rw-r--r-- | src/corelib/thread/qfutureinterface.cpp | 21 |
1 files changed, 6 insertions, 15 deletions
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp index a54caa878b..efbcf9ce58 100644 --- a/src/corelib/thread/qfutureinterface.cpp +++ b/src/corelib/thread/qfutureinterface.cpp @@ -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() |