Get rid of the evilness of Q_GLOBAL_STATIC_WITH_INITIALIZER

That macro is a nightmare. It leads to writing code that is
thread-unsafe or other problems. So rewrite the code that used this
macro to use special-purpose classes with constructors.

This commit does not introduce new errors. The FIXME in qicon.cpp
(qtIconCache()) was a condition already present. It does fix the race
conditions that were present in qbrush.cpp nullBrushInstance() and
qfontengine.cpp qt_grayPalette().

Specialising QGlobalStatic is also evil.

Change-Id: I039311f6a5ac9ea4ad7b310b870a2adf888da7e5
Merge-request: 10
Reviewed-by: Olivier Goffart <olivier.goffart@nokia.com>
Reviewed-on: http://codereview.qt.nokia.com/1895
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
This commit is contained in:
Thiago Macieira 2011-07-20 16:06:58 +02:00 committed by Qt by Nokia
parent de587d736a
commit 6d3c064302
5 changed files with 63 additions and 57 deletions

View File

@ -107,8 +107,18 @@ QT_BEGIN_NAMESPACE
static QBasicAtomicInt serialNumCounter = Q_BASIC_ATOMIC_INITIALIZER(1); static QBasicAtomicInt serialNumCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
static void qt_cleanup_icon_cache(); static void qt_cleanup_icon_cache();
typedef QCache<QString, QIcon> IconCache; namespace {
Q_GLOBAL_STATIC_WITH_INITIALIZER(IconCache, qtIconCache, qAddPostRoutine(qt_cleanup_icon_cache)) class IconCache: public QCache<QString, QIcon>
{
public:
IconCache()
{
// ### FIXME: needs to be re-added if qApp is re-created
qAddPostRoutine(qt_cleanup_icon_cache);
}
};
}
Q_GLOBAL_STATIC(IconCache, qtIconCache)
static void qt_cleanup_icon_cache() static void qt_cleanup_icon_cache()
{ {

View File

@ -112,6 +112,7 @@ QPixmap qt_pixmapForBrush(int brushStyle, bool invert)
return pm; return pm;
} }
static void qt_cleanup_brush_pattern_image_cache();
class QBrushPatternImageCache class QBrushPatternImageCache
{ {
public: public:
@ -123,6 +124,7 @@ public:
void init() void init()
{ {
qAddPostRoutine(qt_cleanup_brush_pattern_image_cache);
for (int style = Qt::Dense1Pattern; style <= Qt::DiagCrossPattern; ++style) { for (int style = Qt::Dense1Pattern; style <= Qt::DiagCrossPattern; ++style) {
int i = style - Qt::Dense1Pattern; int i = style - Qt::Dense1Pattern;
m_images[i][0] = QImage(qt_patternForBrush(style, 0), 8, 8, 1, QImage::Format_MonoLSB); m_images[i][0] = QImage(qt_patternForBrush(style, 0), 8, 8, 1, QImage::Format_MonoLSB);
@ -153,11 +155,7 @@ private:
bool m_initialized; bool m_initialized;
}; };
static void qt_cleanup_brush_pattern_image_cache(); Q_GLOBAL_STATIC(QBrushPatternImageCache, qt_brushPatternImageCache)
Q_GLOBAL_STATIC_WITH_INITIALIZER(QBrushPatternImageCache, qt_brushPatternImageCache,
{
qAddPostRoutine(qt_cleanup_brush_pattern_image_cache);
})
static void qt_cleanup_brush_pattern_image_cache() static void qt_cleanup_brush_pattern_image_cache()
{ {
@ -339,33 +337,29 @@ struct QBrushDataPointerDeleter
\sa Qt::BrushStyle, QPainter, QColor \sa Qt::BrushStyle, QPainter, QColor
*/ */
#ifndef QT_NO_THREAD class QNullBrushData
// Special deleter that only deletes if the ref-count goes to zero
template <>
class QGlobalStaticDeleter<QBrushData>
{ {
public: public:
QGlobalStatic<QBrushData> &globalStatic; QBrushData *brush;
QGlobalStaticDeleter(QGlobalStatic<QBrushData> &_globalStatic) QNullBrushData() : brush(new QBrushData)
: globalStatic(_globalStatic)
{ }
inline ~QGlobalStaticDeleter()
{ {
if (!globalStatic.pointer->ref.deref()) brush->ref = 1;
delete globalStatic.pointer; brush->style = Qt::BrushStyle(0);
globalStatic.pointer = 0; brush->color = Qt::black;
globalStatic.destroyed = true; }
~QNullBrushData()
{
if (!brush->ref.deref())
delete brush;
brush = 0;
} }
}; };
#endif
Q_GLOBAL_STATIC_WITH_INITIALIZER(QBrushData, nullBrushInstance, Q_GLOBAL_STATIC(QNullBrushData, nullBrushInstance_holder)
{ static QBrushData *nullBrushInstance()
x->ref = 1; {
x->style = Qt::BrushStyle(0); return nullBrushInstance_holder()->brush;
x->color = Qt::black; }
})
static bool qbrush_check_type(Qt::BrushStyle style) { static bool qbrush_check_type(Qt::BrushStyle style) {
switch (style) { switch (style) {

View File

@ -244,30 +244,25 @@ inline QPenPrivate::QPenPrivate(const QBrush &_brush, qreal _width, Qt::PenStyle
static const Qt::PenCapStyle qpen_default_cap = Qt::SquareCap; static const Qt::PenCapStyle qpen_default_cap = Qt::SquareCap;
static const Qt::PenJoinStyle qpen_default_join = Qt::BevelJoin; static const Qt::PenJoinStyle qpen_default_join = Qt::BevelJoin;
#ifndef QT_NO_THREAD class QPenDataHolder
// Special deleter that only deletes if the ref-count goes to zero
template <>
class QGlobalStaticDeleter<QPenPrivate>
{ {
public: public:
QGlobalStatic<QPenPrivate> &globalStatic; QPenData *pen;
QGlobalStaticDeleter(QGlobalStatic<QPenPrivate> &_globalStatic) QPenDataHolder(const QBrush &brush, qreal width, Qt::PenStyle penStyle,
: globalStatic(_globalStatic) Qt::PenCapStyle penCapStyle, Qt::PenJoinStyle _joinStyle)
: pen(new QPenData(brush, width, penStyle, penCapStyle, _joinStyle))
{ } { }
~QPenDataHolder()
inline ~QGlobalStaticDeleter()
{ {
if (!globalStatic.pointer->ref.deref()) if (!pen->ref.deref())
delete globalStatic.pointer; delete pen;
globalStatic.pointer = 0; pen = 0;
globalStatic.destroyed = true;
} }
}; };
#endif
Q_GLOBAL_STATIC_WITH_ARGS(QPenData, defaultPenInstance, Q_GLOBAL_STATIC_WITH_ARGS(QPenDataHolder, defaultPenInstance,
(Qt::black, 0, Qt::SolidLine, qpen_default_cap, qpen_default_join)) (Qt::black, 0, Qt::SolidLine, qpen_default_cap, qpen_default_join))
Q_GLOBAL_STATIC_WITH_ARGS(QPenData, nullPenInstance, Q_GLOBAL_STATIC_WITH_ARGS(QPenDataHolder, nullPenInstance,
(Qt::black, 0, Qt::NoPen, qpen_default_cap, qpen_default_join)) (Qt::black, 0, Qt::NoPen, qpen_default_cap, qpen_default_join))
/*! /*!
@ -276,7 +271,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QPenData, nullPenInstance,
QPen::QPen() QPen::QPen()
{ {
d = defaultPenInstance(); d = defaultPenInstance()->pen;
d->ref.ref(); d->ref.ref();
} }
@ -289,7 +284,7 @@ QPen::QPen()
QPen::QPen(Qt::PenStyle style) QPen::QPen(Qt::PenStyle style)
{ {
if (style == Qt::NoPen) { if (style == Qt::NoPen) {
d = nullPenInstance(); d = nullPenInstance()->pen;
d->ref.ref(); d->ref.ref();
} else { } else {
d = new QPenData(Qt::black, 0, style, qpen_default_cap, qpen_default_join); d = new QPenData(Qt::black, 0, style, qpen_default_cap, qpen_default_join);

View File

@ -1110,12 +1110,19 @@ QByteArray QFontEngine::convertToPostscriptFontFamilyName(const QByteArray &fami
return f; return f;
} }
Q_GLOBAL_STATIC_WITH_INITIALIZER(QVector<QRgb>, qt_grayPalette, { class QRgbGreyPalette: public QVector<QRgb>
x->resize(256); {
QRgb *it = x->data(); public:
for (int i = 0; i < x->size(); ++i, ++it) QRgbGreyPalette()
*it = 0xff000000 | i | (i<<8) | (i<<16); {
}) resize(256);
QRgb *it = data();
for (int i = 0; i < size(); ++i, ++it)
*it = 0xff000000 | i | (i<<8) | (i<<16);
}
};
Q_GLOBAL_STATIC(QVector<QRgb>, qt_grayPalette)
const QVector<QRgb> &QFontEngine::grayPalette() const QVector<QRgb> &QFontEngine::grayPalette()
{ {

View File

@ -178,6 +178,8 @@ QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL)
#endif #endif
} }
static void qt_cleanup_gl_share_widget();
// //
// QGLWindowSurface // QGLWindowSurface
// //
@ -185,6 +187,8 @@ class QGLGlobalShareWidget
{ {
public: public:
QGLGlobalShareWidget() : firstPixmap(0), widgetRefCount(0), widget(0), initializing(false) { QGLGlobalShareWidget() : firstPixmap(0), widgetRefCount(0), widget(0), initializing(false) {
// ### FIXME - readd the post routine if the qApp is recreated
qAddPostRoutine(qt_cleanup_gl_share_widget);
created = true; created = true;
} }
@ -238,11 +242,7 @@ private:
bool QGLGlobalShareWidget::cleanedUp = false; bool QGLGlobalShareWidget::cleanedUp = false;
bool QGLGlobalShareWidget::created = false; bool QGLGlobalShareWidget::created = false;
static void qt_cleanup_gl_share_widget(); Q_GLOBAL_STATIC(QGLGlobalShareWidget, _qt_gl_share_widget)
Q_GLOBAL_STATIC_WITH_INITIALIZER(QGLGlobalShareWidget, _qt_gl_share_widget,
{
qAddPostRoutine(qt_cleanup_gl_share_widget);
})
static void qt_cleanup_gl_share_widget() static void qt_cleanup_gl_share_widget()
{ {