mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-23 18:32:55 +00:00
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:
parent
6efbe30ee4
commit
69e4c8a3ac
14 changed files with 36 additions and 171 deletions
|
@ -665,8 +665,6 @@ katie_generate_obsolete(QFutureIterator QtCore qfuture.h)
|
|||
katie_generate_obsolete(QFutureWatcherBase QtCore qfuturewatcher.h)
|
||||
katie_generate_obsolete(QGenericArgument 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(QGradientStop QtGui qbrush.h)
|
||||
katie_generate_obsolete(QGradientStops QtGui qbrush.h)
|
||||
|
|
|
@ -62,8 +62,6 @@ include/katie/QtCore/QFutureWatcher
|
|||
include/katie/QtCore/QFutureWatcherBase
|
||||
include/katie/QtCore/QGenericArgument
|
||||
include/katie/QtCore/QGenericReturnArgument
|
||||
include/katie/QtCore/QGlobalStatic
|
||||
include/katie/QtCore/QGlobalStaticDeleter
|
||||
include/katie/QtCore/QHash
|
||||
include/katie/QtCore/QHashData
|
||||
include/katie/QtCore/QHashIterator
|
||||
|
|
|
@ -65,8 +65,6 @@ include/katie/QtCore/QFutureWatcher
|
|||
include/katie/QtCore/QFutureWatcherBase
|
||||
include/katie/QtCore/QGenericArgument
|
||||
include/katie/QtCore/QGenericReturnArgument
|
||||
include/katie/QtCore/QGlobalStatic
|
||||
include/katie/QtCore/QGlobalStaticDeleter
|
||||
include/katie/QtCore/QHash
|
||||
include/katie/QtCore/QHashData
|
||||
include/katie/QtCore/QHashIterator
|
||||
|
|
|
@ -65,8 +65,6 @@ include/katie/QtCore/QFutureWatcher
|
|||
include/katie/QtCore/QFutureWatcherBase
|
||||
include/katie/QtCore/QGenericArgument
|
||||
include/katie/QtCore/QGenericReturnArgument
|
||||
include/katie/QtCore/QGlobalStatic
|
||||
include/katie/QtCore/QGlobalStaticDeleter
|
||||
include/katie/QtCore/QHash
|
||||
include/katie/QtCore/QHashData
|
||||
include/katie/QtCore/QHashIterator
|
||||
|
|
|
@ -29,8 +29,6 @@ incmap = {
|
|||
'QFutureWatcherBase': 'qfuturewatcher.h',
|
||||
'QGenericArgument': 'qobjectdefs.h',
|
||||
'QGenericReturnArgument': 'qobjectdefs.h',
|
||||
'QGlobalStatic': 'qglobal.h',
|
||||
'QGlobalStaticDeleter': 'qglobal.h',
|
||||
'QHashData': 'qhash.h',
|
||||
'QHashIterator': 'qhash.h',
|
||||
'QHashNode': 'qhash.h',
|
||||
|
|
|
@ -261,8 +261,6 @@ classlist = [
|
|||
"QGenericArgument",
|
||||
"QGenericMatrix",
|
||||
"QGenericReturnArgument",
|
||||
"QGlobalStatic",
|
||||
"QGlobalStaticDeleter",
|
||||
"QGradient",
|
||||
"QGradientStop",
|
||||
"QGradientStops",
|
||||
|
|
|
@ -1727,25 +1727,6 @@ bool QInternal::activateCallbacks(void **parameters)
|
|||
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
|
||||
\internal
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include <utility> // std::swap
|
||||
#include <cstdint> // std::uintptr_t
|
||||
#include <memory> // std::unique_ptr
|
||||
|
||||
typedef unsigned char uchar;
|
||||
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 *);
|
||||
Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler);
|
||||
|
||||
|
||||
#if defined(QT_NO_THREAD)
|
||||
|
||||
template <typename T>
|
||||
class QGlobalStatic
|
||||
{
|
||||
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(TYPE, NAME) \
|
||||
static TYPE *NAME() \
|
||||
{ \
|
||||
static std::unique_ptr<TYPE> this__StaticVar_(new TYPE); \
|
||||
return this__StaticVar_.get(); \
|
||||
}
|
||||
|
||||
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
|
||||
static TYPE *NAME() \
|
||||
{ \
|
||||
static TYPE thisVariable ARGS; \
|
||||
static QGlobalStatic<TYPE > thisGlobalStatic(&thisVariable); \
|
||||
return thisGlobalStatic.pointer; \
|
||||
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
|
||||
static TYPE *NAME() \
|
||||
{ \
|
||||
static std::unique_ptr<TYPE> this__StaticVar_(new TYPE ARGS); \
|
||||
return this__StaticVar_.get(); \
|
||||
}
|
||||
|
||||
#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
|
||||
*/
|
||||
|
|
|
@ -24,25 +24,6 @@ QT_BEGIN_NAMESPACE
|
|||
arraytype arrayname[arraysize]; \
|
||||
::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_rad2deg = qreal(57.295779513082320876798154814105); /* 180/pi */
|
||||
|
||||
|
|
|
@ -99,17 +99,21 @@ Qt::BrushStyle BrushPropertyManager::brushStyleIndexToStyle(int brushStyleIndex)
|
|||
return Qt::NoBrush;
|
||||
}
|
||||
|
||||
|
||||
typedef QMap<int, QIcon> EnumIndexIconMap;
|
||||
|
||||
static void clearBrushIcons();
|
||||
Q_GLOBAL_STATIC_WITH_INITIALIZER(EnumIndexIconMap, brushIcons, qAddPostRoutine(clearBrushIcons))
|
||||
Q_GLOBAL_STATIC(EnumIndexIconMap, brushIcons)
|
||||
|
||||
static void clearBrushIcons()
|
||||
{
|
||||
brushIcons()->clear();
|
||||
}
|
||||
|
||||
static int brushIconsCleanup()
|
||||
{
|
||||
qAddPostRoutine(clearBrushIcons);
|
||||
return 0;
|
||||
}
|
||||
Q_CONSTRUCTOR_FUNCTION(brushIconsCleanup)
|
||||
|
||||
const BrushPropertyManager::EnumIndexIconMap &BrushPropertyManager::brushStyleIcons()
|
||||
{
|
||||
// Create a map of icons for the brush style editor
|
||||
|
|
|
@ -138,7 +138,7 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QTHREADLOCAL(QUnifiedTimer, unifiedTimer);
|
||||
thread_local std::unique_ptr<QUnifiedTimer> unifiedTimer(nullptr);
|
||||
|
||||
QUnifiedTimer::QUnifiedTimer() :
|
||||
QObject(), lastTick(0), currentAnimationIdx(0), insideTick(false),
|
||||
|
@ -152,9 +152,9 @@ QUnifiedTimer::QUnifiedTimer() :
|
|||
QUnifiedTimer *QUnifiedTimer::instance()
|
||||
{
|
||||
if (!unifiedTimer) {
|
||||
unifiedTimer = new QUnifiedTimer;
|
||||
unifiedTimer = std::make_unique<QUnifiedTimer>();
|
||||
}
|
||||
return unifiedTimer;
|
||||
return unifiedTimer.get();
|
||||
}
|
||||
|
||||
void QUnifiedTimer::ensureTimerUpdate()
|
||||
|
@ -273,7 +273,7 @@ void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
|
|||
--unifiedTimer->currentAnimationIdx;
|
||||
|
||||
if (unifiedTimer->animations.isEmpty() && !unifiedTimer->startStopAnimationTimer.isActive())
|
||||
unifiedTimer->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, unifiedTimer);
|
||||
unifiedTimer->startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, unifiedTimer.get());
|
||||
} else {
|
||||
unifiedTimer->animationsToStart.removeOne(animation);
|
||||
}
|
||||
|
|
|
@ -115,10 +115,9 @@ public:
|
|||
|
||||
class Q_GUI_EXPORT QUnifiedTimer : public QObject
|
||||
{
|
||||
private:
|
||||
public:
|
||||
QUnifiedTimer();
|
||||
|
||||
public:
|
||||
//XXX this is needed by dui
|
||||
static QUnifiedTimer *instance();
|
||||
|
||||
|
|
|
@ -1614,14 +1614,14 @@ bool QFontInfo::exactMatch() const
|
|||
|
||||
// **********************************************************************
|
||||
// QFontCache
|
||||
QTHREADLOCAL(QFontCache, theFontCache);
|
||||
thread_local std::unique_ptr<QFontCache> theFontCache(nullptr);
|
||||
|
||||
QFontCache *QFontCache::instance()
|
||||
{
|
||||
if (!theFontCache) {
|
||||
theFontCache = new QFontCache();
|
||||
theFontCache = std::make_unique<QFontCache>();
|
||||
}
|
||||
return theFontCache;
|
||||
return theFontCache.get();
|
||||
}
|
||||
|
||||
QFontCache::QFontCache()
|
||||
|
|
|
@ -6276,16 +6276,22 @@ void QtColorPropertyManager::uninitializeProperty(QtProperty *property)
|
|||
|
||||
// QtCursorPropertyManager
|
||||
|
||||
Q_GLOBAL_STATIC(QtCursorDatabase, propertyCursorDatabase)
|
||||
|
||||
// Make sure icons are removed as soon as QApplication is destroyed, otherwise,
|
||||
// handles are leaked on X11.
|
||||
static void clearCursorDatabase();
|
||||
Q_GLOBAL_STATIC_WITH_INITIALIZER(QtCursorDatabase, propertyCursorDatabase, qAddPostRoutine(clearCursorDatabase))
|
||||
|
||||
static void clearCursorDatabase()
|
||||
{
|
||||
propertyCursorDatabase()->clear();
|
||||
}
|
||||
|
||||
static int propertyCursorDatabaseCleanup()
|
||||
{
|
||||
qAddPostRoutine(clearCursorDatabase);
|
||||
return 0;
|
||||
}
|
||||
Q_CONSTRUCTOR_FUNCTION(propertyCursorDatabaseCleanup)
|
||||
|
||||
class QtCursorPropertyManagerPrivate
|
||||
{
|
||||
QtCursorPropertyManager *q_ptr;
|
||||
|
|
Loading…
Add table
Reference in a new issue