get rid of the subject to race condition Q_GLOBAL_STATIC_WITH_INITIALIZER() macro [ci reset]

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-01-25 15:51:33 +02:00
parent 6efbe30ee4
commit 69e4c8a3ac
14 changed files with 36 additions and 171 deletions

View file

@ -665,8 +665,6 @@ katie_generate_obsolete(QFutureIterator QtCore qfuture.h)
katie_generate_obsolete(QFutureWatcherBase QtCore qfuturewatcher.h) katie_generate_obsolete(QFutureWatcherBase QtCore qfuturewatcher.h)
katie_generate_obsolete(QGenericArgument QtCore qobjectdefs.h) katie_generate_obsolete(QGenericArgument QtCore qobjectdefs.h)
katie_generate_obsolete(QGenericReturnArgument QtCore qobjectdefs.h) katie_generate_obsolete(QGenericReturnArgument QtCore qobjectdefs.h)
katie_generate_obsolete(QGlobalStaticDeleter QtCore qglobal.h)
katie_generate_obsolete(QGlobalStatic QtCore qglobal.h)
katie_generate_obsolete(QGradient QtGui qbrush.h) katie_generate_obsolete(QGradient QtGui qbrush.h)
katie_generate_obsolete(QGradientStop QtGui qbrush.h) katie_generate_obsolete(QGradientStop QtGui qbrush.h)
katie_generate_obsolete(QGradientStops QtGui qbrush.h) katie_generate_obsolete(QGradientStops QtGui qbrush.h)

View file

@ -62,8 +62,6 @@ include/katie/QtCore/QFutureWatcher
include/katie/QtCore/QFutureWatcherBase include/katie/QtCore/QFutureWatcherBase
include/katie/QtCore/QGenericArgument include/katie/QtCore/QGenericArgument
include/katie/QtCore/QGenericReturnArgument include/katie/QtCore/QGenericReturnArgument
include/katie/QtCore/QGlobalStatic
include/katie/QtCore/QGlobalStaticDeleter
include/katie/QtCore/QHash include/katie/QtCore/QHash
include/katie/QtCore/QHashData include/katie/QtCore/QHashData
include/katie/QtCore/QHashIterator include/katie/QtCore/QHashIterator

View file

@ -65,8 +65,6 @@ include/katie/QtCore/QFutureWatcher
include/katie/QtCore/QFutureWatcherBase include/katie/QtCore/QFutureWatcherBase
include/katie/QtCore/QGenericArgument include/katie/QtCore/QGenericArgument
include/katie/QtCore/QGenericReturnArgument include/katie/QtCore/QGenericReturnArgument
include/katie/QtCore/QGlobalStatic
include/katie/QtCore/QGlobalStaticDeleter
include/katie/QtCore/QHash include/katie/QtCore/QHash
include/katie/QtCore/QHashData include/katie/QtCore/QHashData
include/katie/QtCore/QHashIterator include/katie/QtCore/QHashIterator

View file

@ -65,8 +65,6 @@ include/katie/QtCore/QFutureWatcher
include/katie/QtCore/QFutureWatcherBase include/katie/QtCore/QFutureWatcherBase
include/katie/QtCore/QGenericArgument include/katie/QtCore/QGenericArgument
include/katie/QtCore/QGenericReturnArgument include/katie/QtCore/QGenericReturnArgument
include/katie/QtCore/QGlobalStatic
include/katie/QtCore/QGlobalStaticDeleter
include/katie/QtCore/QHash include/katie/QtCore/QHash
include/katie/QtCore/QHashData include/katie/QtCore/QHashData
include/katie/QtCore/QHashIterator include/katie/QtCore/QHashIterator

View file

@ -29,8 +29,6 @@ incmap = {
'QFutureWatcherBase': 'qfuturewatcher.h', 'QFutureWatcherBase': 'qfuturewatcher.h',
'QGenericArgument': 'qobjectdefs.h', 'QGenericArgument': 'qobjectdefs.h',
'QGenericReturnArgument': 'qobjectdefs.h', 'QGenericReturnArgument': 'qobjectdefs.h',
'QGlobalStatic': 'qglobal.h',
'QGlobalStaticDeleter': 'qglobal.h',
'QHashData': 'qhash.h', 'QHashData': 'qhash.h',
'QHashIterator': 'qhash.h', 'QHashIterator': 'qhash.h',
'QHashNode': 'qhash.h', 'QHashNode': 'qhash.h',

View file

@ -261,8 +261,6 @@ classlist = [
"QGenericArgument", "QGenericArgument",
"QGenericMatrix", "QGenericMatrix",
"QGenericReturnArgument", "QGenericReturnArgument",
"QGlobalStatic",
"QGlobalStaticDeleter",
"QGradient", "QGradient",
"QGradientStop", "QGradientStop",
"QGradientStops", "QGradientStops",

View file

@ -1727,25 +1727,6 @@ bool QInternal::activateCallbacks(void **parameters)
to it. to it.
*/ */
/*!
\macro Q_GLOBAL_STATIC_WITH_INITIALIZER(type, name, initializer)
\internal
Declares a global static variable with the specified \a type and \a name.
Use this macro to instantiate an object using the \a initializer specified
in a thread-safe way, creating a global pointer that can be used to refer
to it.
\warning This macro is subject to a race condition that can cause the object
to be constructed twice. However, if this occurs, the second instance will
be immediately deleted.
See also
\l{http://www.aristeia.com/publications.html}{"C++ and the perils of Double-Checked Locking"}
by Scott Meyers and Andrei Alexandrescu.
*/
/*! /*!
\macro QT_NAMESPACE \macro QT_NAMESPACE
\internal \internal

View file

@ -36,6 +36,7 @@
#include <utility> // std::swap #include <utility> // std::swap
#include <cstdint> // std::uintptr_t #include <cstdint> // std::uintptr_t
#include <memory> // std::unique_ptr
typedef unsigned char uchar; typedef unsigned char uchar;
typedef unsigned short ushort; typedef unsigned short ushort;
@ -393,115 +394,20 @@ Q_CORE_EXPORT void qt_message_output(QtMsgType, const char *buf);
typedef void (*QtMsgHandler)(QtMsgType, const char *); typedef void (*QtMsgHandler)(QtMsgType, const char *);
Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler); Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler);
#define Q_GLOBAL_STATIC(TYPE, NAME) \
#if defined(QT_NO_THREAD) static TYPE *NAME() \
{ \
template <typename T> static std::unique_ptr<TYPE> this__StaticVar_(new TYPE); \
class QGlobalStatic return this__StaticVar_.get(); \
{
public:
T *pointer;
inline QGlobalStatic(T *p) : pointer(p) { }
inline ~QGlobalStatic() { pointer = nullptr; }
};
#define Q_GLOBAL_STATIC(TYPE, NAME) \
static TYPE *NAME() \
{ \
static TYPE thisVariable; \
static QGlobalStatic<TYPE > thisGlobalStatic(&thisVariable); \
return thisGlobalStatic.pointer; \
} }
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \ #define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
static TYPE *NAME() \ static TYPE *NAME() \
{ \ { \
static TYPE thisVariable ARGS; \ static std::unique_ptr<TYPE> this__StaticVar_(new TYPE ARGS); \
static QGlobalStatic<TYPE > thisGlobalStatic(&thisVariable); \ return this__StaticVar_.get(); \
return thisGlobalStatic.pointer; \
} }
#define Q_GLOBAL_STATIC_WITH_INITIALIZER(TYPE, NAME, INITIALIZER) \
static TYPE *NAME() \
{ \
static TYPE thisVariable; \
static QGlobalStatic<TYPE > thisGlobalStatic(nullptr); \
if (!thisGlobalStatic.pointer) { \
TYPE *x = thisGlobalStatic.pointer = &thisVariable; \
INITIALIZER; \
} \
return thisGlobalStatic.pointer; \
}
#else // QT_NO_THREAD
// Forward declaration, since qatomic.h needs qglobal.h
template <typename T> class QAtomicPointer;
// POD for Q_GLOBAL_STATIC
template <typename T>
class QGlobalStatic
{
public:
QAtomicPointer<T> pointer;
bool destroyed;
};
// Created as a function-local static to delete a QGlobalStatic<T>
template <typename T>
class QGlobalStaticDeleter
{
public:
QGlobalStatic<T> &globalStatic;
QGlobalStaticDeleter(QGlobalStatic<T> &_globalStatic)
: globalStatic(_globalStatic)
{ }
inline ~QGlobalStaticDeleter()
{
delete globalStatic.pointer;
globalStatic.pointer = nullptr;
globalStatic.destroyed = true;
}
};
#define Q_GLOBAL_STATIC(TYPE, NAME) \
static TYPE *NAME() \
{ \
static QGlobalStatic<TYPE > this__StaticVar_ \
= { QAtomicPointer<TYPE>(new TYPE), false }; \
static QGlobalStaticDeleter<TYPE > cleanup(this__StaticVar_); \
return this__StaticVar_.pointer; \
}
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
static TYPE *NAME() \
{ \
static QGlobalStatic<TYPE > this__StaticVar_ \
= { QAtomicPointer<TYPE>(new TYPE ARGS), false }; \
static QGlobalStaticDeleter<TYPE > cleanup(this__StaticVar_); \
return this__StaticVar_.pointer; \
}
#define Q_GLOBAL_STATIC_WITH_INITIALIZER(TYPE, NAME, INITIALIZER) \
static TYPE *NAME() \
{ \
static QGlobalStatic<TYPE > this__StaticVar_ \
= { QAtomicPointer<TYPE>(nullptr), false }; \
if (!this__StaticVar_.pointer && !this__StaticVar_.destroyed) { \
QScopedPointer<TYPE > x(new TYPE); \
INITIALIZER; \
if (this__StaticVar_.pointer.testAndSetOrdered(nullptr, x.data())) { \
static QGlobalStaticDeleter<TYPE > cleanup(this__StaticVar_); \
x.take(); \
} \
} \
return this__StaticVar_.pointer; \
}
#endif // QT_NO_THREAD
/* /*
Utility macros and inline functions Utility macros and inline functions
*/ */

View file

@ -24,25 +24,6 @@ QT_BEGIN_NAMESPACE
arraytype arrayname[arraysize]; \ arraytype arrayname[arraysize]; \
::memset(arrayname, 0, arraysize * sizeof(arraytype)); ::memset(arrayname, 0, arraysize * sizeof(arraytype));
template <typename T>
class QThreadLocalDeleter
{
public:
T* threadLocal;
QThreadLocalDeleter(T* _threadLocal)
: threadLocal(_threadLocal)
{ }
inline ~QThreadLocalDeleter()
{
delete threadLocal;
}
};
#define QTHREADLOCAL(localtype, localname) \
thread_local localtype* localname(nullptr); \
thread_local QThreadLocalDeleter<localtype> localname## _deleter(localname);
static const qreal q_deg2rad = qreal(0.01745329251994329576923690768489); /* pi/180 */ static const qreal q_deg2rad = qreal(0.01745329251994329576923690768489); /* pi/180 */
static const qreal q_rad2deg = qreal(57.295779513082320876798154814105); /* 180/pi */ static const qreal q_rad2deg = qreal(57.295779513082320876798154814105); /* 180/pi */

View file

@ -99,17 +99,21 @@ Qt::BrushStyle BrushPropertyManager::brushStyleIndexToStyle(int brushStyleIndex)
return Qt::NoBrush; return Qt::NoBrush;
} }
typedef QMap<int, QIcon> EnumIndexIconMap; typedef QMap<int, QIcon> EnumIndexIconMap;
Q_GLOBAL_STATIC(EnumIndexIconMap, brushIcons)
static void clearBrushIcons();
Q_GLOBAL_STATIC_WITH_INITIALIZER(EnumIndexIconMap, brushIcons, qAddPostRoutine(clearBrushIcons))
static void clearBrushIcons() static void clearBrushIcons()
{ {
brushIcons()->clear(); brushIcons()->clear();
} }
static int brushIconsCleanup()
{
qAddPostRoutine(clearBrushIcons);
return 0;
}
Q_CONSTRUCTOR_FUNCTION(brushIconsCleanup)
const BrushPropertyManager::EnumIndexIconMap &BrushPropertyManager::brushStyleIcons() const BrushPropertyManager::EnumIndexIconMap &BrushPropertyManager::brushStyleIcons()
{ {
// Create a map of icons for the brush style editor // Create a map of icons for the brush style editor

View file

@ -138,7 +138,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QTHREADLOCAL(QUnifiedTimer, unifiedTimer); thread_local std::unique_ptr<QUnifiedTimer> unifiedTimer(nullptr);
QUnifiedTimer::QUnifiedTimer() : QUnifiedTimer::QUnifiedTimer() :
QObject(), lastTick(0), currentAnimationIdx(0), insideTick(false), QObject(), lastTick(0), currentAnimationIdx(0), insideTick(false),
@ -152,9 +152,9 @@ QUnifiedTimer::QUnifiedTimer() :
QUnifiedTimer *QUnifiedTimer::instance() QUnifiedTimer *QUnifiedTimer::instance()
{ {
if (!unifiedTimer) { if (!unifiedTimer) {
unifiedTimer = new QUnifiedTimer; unifiedTimer = std::make_unique<QUnifiedTimer>();
} }
return unifiedTimer; return unifiedTimer.get();
} }
void QUnifiedTimer::ensureTimerUpdate() void QUnifiedTimer::ensureTimerUpdate()
@ -273,7 +273,7 @@ void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
--unifiedTimer->currentAnimationIdx; --unifiedTimer->currentAnimationIdx;
if (unifiedTimer->animations.isEmpty() && !unifiedTimer->startStopAnimationTimer.isActive()) if (unifiedTimer->animations.isEmpty() && !unifiedTimer->startStopAnimationTimer.isActive())
unifiedTimer->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, unifiedTimer); unifiedTimer->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, unifiedTimer.get());
} else { } else {
unifiedTimer->animationsToStart.removeOne(animation); unifiedTimer->animationsToStart.removeOne(animation);
} }

View file

@ -115,10 +115,9 @@ public:
class Q_GUI_EXPORT QUnifiedTimer : public QObject class Q_GUI_EXPORT QUnifiedTimer : public QObject
{ {
private: public:
QUnifiedTimer(); QUnifiedTimer();
public:
//XXX this is needed by dui //XXX this is needed by dui
static QUnifiedTimer *instance(); static QUnifiedTimer *instance();

View file

@ -1614,14 +1614,14 @@ bool QFontInfo::exactMatch() const
// ********************************************************************** // **********************************************************************
// QFontCache // QFontCache
QTHREADLOCAL(QFontCache, theFontCache); thread_local std::unique_ptr<QFontCache> theFontCache(nullptr);
QFontCache *QFontCache::instance() QFontCache *QFontCache::instance()
{ {
if (!theFontCache) { if (!theFontCache) {
theFontCache = new QFontCache(); theFontCache = std::make_unique<QFontCache>();
} }
return theFontCache; return theFontCache.get();
} }
QFontCache::QFontCache() QFontCache::QFontCache()

View file

@ -6276,16 +6276,22 @@ void QtColorPropertyManager::uninitializeProperty(QtProperty *property)
// QtCursorPropertyManager // QtCursorPropertyManager
Q_GLOBAL_STATIC(QtCursorDatabase, propertyCursorDatabase)
// Make sure icons are removed as soon as QApplication is destroyed, otherwise, // Make sure icons are removed as soon as QApplication is destroyed, otherwise,
// handles are leaked on X11. // handles are leaked on X11.
static void clearCursorDatabase();
Q_GLOBAL_STATIC_WITH_INITIALIZER(QtCursorDatabase, propertyCursorDatabase, qAddPostRoutine(clearCursorDatabase))
static void clearCursorDatabase() static void clearCursorDatabase()
{ {
propertyCursorDatabase()->clear(); propertyCursorDatabase()->clear();
} }
static int propertyCursorDatabaseCleanup()
{
qAddPostRoutine(clearCursorDatabase);
return 0;
}
Q_CONSTRUCTOR_FUNCTION(propertyCursorDatabaseCleanup)
class QtCursorPropertyManagerPrivate class QtCursorPropertyManagerPrivate
{ {
QtCursorPropertyManager *q_ptr; QtCursorPropertyManager *q_ptr;