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 <marc.mutz@qt.io>
This commit is contained in:
Thiago Macieira 2018-07-11 10:00:43 -07:00
parent de6ced6692
commit 4a93285b16
3 changed files with 18 additions and 43 deletions

View File

@ -149,7 +149,6 @@
#include "qabstractanimation_p.h" #include "qabstractanimation_p.h"
#include <QtCore/qmath.h> #include <QtCore/qmath.h>
#include <QtCore/qthreadstorage.h>
#include <QtCore/qcoreevent.h> #include <QtCore/qcoreevent.h>
#include <QtCore/qpointer.h> #include <QtCore/qpointer.h>
#include <QtCore/qscopedvaluerollback.h> #include <QtCore/qscopedvaluerollback.h>
@ -214,8 +213,6 @@ typedef QList<QAbstractAnimation*>::ConstIterator AnimationListConstIt;
QUnifiedTimer drives animations indirectly, via QAbstractAnimationTimer. QUnifiedTimer drives animations indirectly, via QAbstractAnimationTimer.
*/ */
Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer)
QUnifiedTimer::QUnifiedTimer() : QUnifiedTimer::QUnifiedTimer() :
QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL),
currentAnimationIdx(0), insideTick(false), insideRestart(false), consistentTiming(false), slowMode(false), currentAnimationIdx(0), insideTick(false), insideRestart(false), consistentTiming(false), slowMode(false),
@ -233,11 +230,12 @@ QUnifiedTimer::~QUnifiedTimer()
QUnifiedTimer *QUnifiedTimer::instance(bool create) QUnifiedTimer *QUnifiedTimer::instance(bool create)
{ {
QUnifiedTimer *inst; QUnifiedTimer *inst;
if (create && !unifiedTimer()->hasLocalData()) { static thread_local std::unique_ptr<QUnifiedTimer> unifiedTimer;
if (create && !unifiedTimer) {
inst = new QUnifiedTimer; inst = new QUnifiedTimer;
unifiedTimer()->setLocalData(inst); unifiedTimer.reset(inst);
} else { } else {
inst = unifiedTimer() ? unifiedTimer()->localData() : nullptr; inst = unifiedTimer.get();
} }
return inst; return inst;
} }
@ -550,10 +548,6 @@ bool QUnifiedTimer::canUninstallAnimationDriver(QAnimationDriver *d)
return d == driver && driver != &defaultDriver; return d == driver && driver != &defaultDriver;
} }
#if QT_CONFIG(thread)
Q_GLOBAL_STATIC(QThreadStorage<QAnimationTimer *>, animationTimer)
#endif
QAnimationTimer::QAnimationTimer() : QAnimationTimer::QAnimationTimer() :
QAbstractAnimationTimer(), lastTick(0), QAbstractAnimationTimer(), lastTick(0),
currentAnimationIdx(0), insideTick(false), currentAnimationIdx(0), insideTick(false),
@ -569,11 +563,12 @@ QAnimationTimer *QAnimationTimer::instance(bool create)
{ {
QAnimationTimer *inst; QAnimationTimer *inst;
#if QT_CONFIG(thread) #if QT_CONFIG(thread)
if (create && !animationTimer()->hasLocalData()) { static thread_local std::unique_ptr<QAnimationTimer> animationTimer;
if (create && !animationTimer) {
inst = new QAnimationTimer; inst = new QAnimationTimer;
animationTimer()->setLocalData(inst); animationTimer.reset(inst);
} else { } else {
inst = animationTimer() ? animationTimer()->localData() : nullptr; inst = animationTimer.get();
} }
#else #else
Q_UNUSED(create); Q_UNUSED(create);

View File

@ -46,7 +46,6 @@
#include <qendian.h> #include <qendian.h>
#include <qmutex.h> #include <qmutex.h>
#include <qobjectdefs.h> #include <qobjectdefs.h>
#include <qthreadstorage.h>
#include <errno.h> #include <errno.h>

View File

@ -47,7 +47,6 @@
#include <QtCore/qmutex.h> #include <QtCore/qmutex.h>
#include <QtCore/qstringlist.h> #include <QtCore/qstringlist.h>
#include <QtCore/qdebug.h> #include <QtCore/qdebug.h>
#include <QtCore/qthreadstorage.h>
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include <QtCore/qatomic.h> #include <QtCore/qatomic.h>
#include <QtCore/qdatastream.h> #include <QtCore/qdatastream.h>
@ -962,43 +961,24 @@ void QRegularExpressionPrivate::getPatternInfo()
Simple "smartpointer" wrapper around a pcre2_jit_stack_16, to be used with Simple "smartpointer" wrapper around a pcre2_jit_stack_16, to be used with
QThreadStorage. QThreadStorage.
*/ */
class QPcreJitStackPointer namespace {
struct PcreJitStackFree
{ {
Q_DISABLE_COPY(QPcreJitStackPointer) void operator()(pcre2_jit_stack_16 *stack)
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()
{ {
if (stack) if (stack)
pcre2_jit_stack_free_16(stack); pcre2_jit_stack_free_16(stack);
} }
pcre2_jit_stack_16 *stack;
}; };
static thread_local std::unique_ptr<pcre2_jit_stack_16, PcreJitStackFree> jitStacks;
Q_GLOBAL_STATIC(QThreadStorage<QPcreJitStackPointer *>, jitStacks) }
/*! /*!
\internal \internal
*/ */
static pcre2_jit_stack_16 *qtPcreCallback(void *) static pcre2_jit_stack_16 *qtPcreCallback(void *)
{ {
if (jitStacks()->hasLocalData()) return jitStacks.get();
return jitStacks()->localData()->stack;
return nullptr;
} }
/*! /*!
@ -1094,9 +1074,10 @@ static int safe_pcre2_match_16(const pcre2_code_16 *code,
int result = pcre2_match_16(code, subject, length, int result = pcre2_match_16(code, subject, length,
startOffset, options, matchData, matchContext); startOffset, options, matchData, matchContext);
if (result == PCRE2_ERROR_JIT_STACKLIMIT && !jitStacks()->hasLocalData()) { if (result == PCRE2_ERROR_JIT_STACKLIMIT && !jitStacks) {
QPcreJitStackPointer *p = new QPcreJitStackPointer; // The default JIT stack size in PCRE is 32K,
jitStacks()->setLocalData(p); // 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, result = pcre2_match_16(code, subject, length,
startOffset, options, matchData, matchContext); startOffset, options, matchData, matchContext);