summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qfutureinterface.cpp
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2022-04-30 10:21:26 +0200
committerMarc Mutz <marc.mutz@qt.io>2022-04-30 23:54:38 +0200
commitc847f0091d484de7b3fb1049838eee3f2ac3dfc5 (patch)
treed3837330a68e4e17bbb974c3219deda61308dcb0 /src/corelib/thread/qfutureinterface.cpp
parent1808df9ce59a8c1d426f0361e25120a7852a6442 (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.cpp21
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()