QString::localeAwareCompare: adapt to QLocale::setDefault() being called

Because we're using a thread-specific global static, we need to recreate
the QCollator type every time setDefault() is called. Since one is
stored per-thread, we simply increment a generational counter and check
that the next time that QString::localeAwareCompare is called in each
thread.

The issue was introduced on f6425da424
(5.12) even though we were supposed to be using QCollator since commit
5279134935 (5.3).

Fixes: QTBUG-95050
Pick-to: 6.2
Change-Id: I7e0b82c2d2fe464082d8fffd1696a8c9f74e5b30
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
bb10
Thiago Macieira 2021-07-30 12:38:20 -07:00
parent 4d2e574fb0
commit 94de5f9b25
3 changed files with 25 additions and 4 deletions

View File

@ -780,9 +780,9 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
}
#endif // QT_NO_DATASTREAM
static const int locale_data_size = sizeof(locale_data)/sizeof(QLocaleData) - 1;
QBasicAtomicInt QLocalePrivate::s_generation = Q_BASIC_ATOMIC_INITIALIZER(0);
Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QLocalePrivate>, defaultLocalePrivate,
(new QLocalePrivate(defaultData(), defaultIndex())))
@ -1206,6 +1206,7 @@ void QLocale::setDefault(const QLocale &locale)
// update the cached private
*defaultLocalePrivate = locale.d;
QLocalePrivate::s_generation.fetchAndAddRelaxed(1);
}
/*!

View File

@ -424,6 +424,8 @@ public:
QBasicAtomicInt ref;
const uint m_index;
QLocale::NumberOptions m_numberOptions;
static QBasicAtomicInt s_generation;
};
#ifndef QT_NO_SYSTEMLOCALE

View File

@ -6141,7 +6141,25 @@ int QString::localeAwareCompare(const QString &other) const
}
#if QT_CONFIG(icu)
Q_GLOBAL_STATIC(QThreadStorage<QCollator>, defaultCollator)
namespace {
class GenerationalCollator
{
QCollator theCollator;
int generation = QLocalePrivate::s_generation.loadRelaxed();
public:
QCollator &collator()
{
int currentGeneration = QLocalePrivate::s_generation.loadRelaxed();
if (Q_UNLIKELY(generation != currentGeneration)) {
// reinitialize the collator
generation = currentGeneration;
theCollator = QCollator();
}
return theCollator;
}
};
}
Q_GLOBAL_STATIC(QThreadStorage<GenerationalCollator>, defaultCollator)
#endif
/*!
@ -6163,8 +6181,8 @@ int QString::localeAwareCompare_helper(const QChar *data1, qsizetype length1,
#if QT_CONFIG(icu)
if (!defaultCollator()->hasLocalData())
defaultCollator()->setLocalData(QCollator());
return defaultCollator()->localData().compare(data1, length1, data2, length2);
defaultCollator()->setLocalData(GenerationalCollator());
return defaultCollator()->localData().collator().compare(data1, length1, data2, length2);
#else
const QString lhs = QString::fromRawData(data1, length1).normalized(QString::NormalizationForm_C);
const QString rhs = QString::fromRawData(data2, length2).normalized(QString::NormalizationForm_C);