From 4a93285b166ceceaea2e10c8fc6a254d2f7093b9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 11 Jul 2018 10:00:43 -0700 Subject: [PATCH] QtCore: use C++11 thread_local instead of QThreadStorage It's more efficient than our QThreadStorage and definitely much better than the Q_GLOBAL_STATIC+QThreadStorage solution. We can do this because the last compiler not to have thread_local support was MSVC 2013, which is no longer supported since Qt 5.11. QThreadStorage also managed the lifetimes of pointers for us, so the equivalent thread_local requires std::unique_ptr. Change-Id: Id59bdd8f1a804b809e22fffd15405f1b394c48d8 Reviewed-by: Marc Mutz --- src/corelib/animation/qabstractanimation.cpp | 21 ++++------- src/corelib/global/qrandom.cpp | 1 - src/corelib/text/qregularexpression.cpp | 39 +++++--------------- 3 files changed, 18 insertions(+), 43 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index ce9cb70565a..181ba437718 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -149,7 +149,6 @@ #include "qabstractanimation_p.h" #include -#include #include #include #include @@ -214,8 +213,6 @@ typedef QList::ConstIterator AnimationListConstIt; QUnifiedTimer drives animations indirectly, via QAbstractAnimationTimer. */ -Q_GLOBAL_STATIC(QThreadStorage, unifiedTimer) - QUnifiedTimer::QUnifiedTimer() : QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), currentAnimationIdx(0), insideTick(false), insideRestart(false), consistentTiming(false), slowMode(false), @@ -233,11 +230,12 @@ QUnifiedTimer::~QUnifiedTimer() QUnifiedTimer *QUnifiedTimer::instance(bool create) { QUnifiedTimer *inst; - if (create && !unifiedTimer()->hasLocalData()) { + static thread_local std::unique_ptr unifiedTimer; + if (create && !unifiedTimer) { inst = new QUnifiedTimer; - unifiedTimer()->setLocalData(inst); + unifiedTimer.reset(inst); } else { - inst = unifiedTimer() ? unifiedTimer()->localData() : nullptr; + inst = unifiedTimer.get(); } return inst; } @@ -550,10 +548,6 @@ bool QUnifiedTimer::canUninstallAnimationDriver(QAnimationDriver *d) return d == driver && driver != &defaultDriver; } -#if QT_CONFIG(thread) -Q_GLOBAL_STATIC(QThreadStorage, animationTimer) -#endif - QAnimationTimer::QAnimationTimer() : QAbstractAnimationTimer(), lastTick(0), currentAnimationIdx(0), insideTick(false), @@ -569,11 +563,12 @@ QAnimationTimer *QAnimationTimer::instance(bool create) { QAnimationTimer *inst; #if QT_CONFIG(thread) - if (create && !animationTimer()->hasLocalData()) { + static thread_local std::unique_ptr animationTimer; + if (create && !animationTimer) { inst = new QAnimationTimer; - animationTimer()->setLocalData(inst); + animationTimer.reset(inst); } else { - inst = animationTimer() ? animationTimer()->localData() : nullptr; + inst = animationTimer.get(); } #else Q_UNUSED(create); diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 34df85133bf..eb7eca63882 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #include diff --git a/src/corelib/text/qregularexpression.cpp b/src/corelib/text/qregularexpression.cpp index 1db27fc4e48..0c8215cebb3 100644 --- a/src/corelib/text/qregularexpression.cpp +++ b/src/corelib/text/qregularexpression.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -962,43 +961,24 @@ void QRegularExpressionPrivate::getPatternInfo() Simple "smartpointer" wrapper around a pcre2_jit_stack_16, to be used with QThreadStorage. */ -class QPcreJitStackPointer +namespace { +struct PcreJitStackFree { - Q_DISABLE_COPY(QPcreJitStackPointer) - -public: - /*! - \internal - */ - QPcreJitStackPointer() - { - // The default JIT stack size in PCRE is 32K, - // we allocate from 32K up to 512K. - stack = pcre2_jit_stack_create_16(32 * 1024, 512 * 1024, nullptr); - } - /*! - \internal - */ - ~QPcreJitStackPointer() + void operator()(pcre2_jit_stack_16 *stack) { if (stack) pcre2_jit_stack_free_16(stack); } - - pcre2_jit_stack_16 *stack; }; - -Q_GLOBAL_STATIC(QThreadStorage, jitStacks) +static thread_local std::unique_ptr jitStacks; +} /*! \internal */ static pcre2_jit_stack_16 *qtPcreCallback(void *) { - if (jitStacks()->hasLocalData()) - return jitStacks()->localData()->stack; - - return nullptr; + return jitStacks.get(); } /*! @@ -1094,9 +1074,10 @@ static int safe_pcre2_match_16(const pcre2_code_16 *code, int result = pcre2_match_16(code, subject, length, startOffset, options, matchData, matchContext); - if (result == PCRE2_ERROR_JIT_STACKLIMIT && !jitStacks()->hasLocalData()) { - QPcreJitStackPointer *p = new QPcreJitStackPointer; - jitStacks()->setLocalData(p); + if (result == PCRE2_ERROR_JIT_STACKLIMIT && !jitStacks) { + // The default JIT stack size in PCRE is 32K, + // we allocate from 32K up to 512K. + jitStacks.reset(pcre2_jit_stack_create_16(32 * 1024, 512 * 1024, NULL)); result = pcre2_match_16(code, subject, length, startOffset, options, matchData, matchContext);