QThreadStorage: add a warning suggesting use of thread_local

thread_local can still be very broken for non-trivial types, 14 years
since C++11 was ratified, but it works plenty well for trivial types. So
suggest users use that (with a macro to opt-out).

[ChangeLog][QtCore][QThreadStorage] QThreadStorage will print a warning
suggesting the use of thread_local for use with primitive types that are
not pointers. In fact, switching to the C++11 functionality is advisable
for all types, but some runtimes have bugs concerning destruction order.
This warning can be suppressed by #define'ing the macro
Q_NO_THREAD_STORAGE_TRIVIAL_WARNING.

This code is actually very old (looks like it has pre-C++98
compatibility support for MSVC 6.0) and could use a refactor, but it's
not worth my time to do it or review it for such old content. Stop using
QThreadStorage if you can.

Task-number: QTBUG-117850
Change-Id: I906ba7872388fc578c78fffd92231118decfd67e
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Thiago Macieira 2025-02-08 15:31:55 -08:00
parent 1df6a48a89
commit 07a15916cc
3 changed files with 17 additions and 1 deletions

View File

@ -14,6 +14,18 @@ QT_BEGIN_NAMESPACE
#if QT_CONFIG(thread)
template <bool ShouldWarn> struct QThreadStorageTraits
{
static constexpr void warnAboutTrivial() {}
};
template <> struct QThreadStorageTraits<true>
{
#ifndef Q_NO_THREAD_STORAGE_TRIVIAL_WARNING
Q_DECL_DEPRECATED_X("QThreadStorage used with a trivial non-pointer type; consider using thread_local")
#endif
static constexpr void warnAboutTrivial() noexcept {}
};
class Q_CORE_EXPORT QThreadStorageData
{
public:
@ -87,6 +99,7 @@ template <class T>
class QThreadStorage
{
private:
using Trait = QThreadStorageTraits<std::is_trivial_v<T> && !std::is_pointer_v<T>>;
QThreadStorageData d;
Q_DISABLE_COPY(QThreadStorage)
@ -95,7 +108,7 @@ private:
{ qThreadStorage_deleteData(x, reinterpret_cast<T*>(0)); }
public:
inline QThreadStorage() : d(deleteData) { }
inline QThreadStorage() : d(deleteData) { Trait::warnAboutTrivial(); }
inline ~QThreadStorage() { }
inline bool hasLocalData() const

View File

@ -1,6 +1,7 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#define Q_NO_THREAD_STORAGE_TRIVIAL_WARNING
#include <QtCore/QCoreApplication>
#include <QtCore/QThreadStorage>

View File

@ -1,6 +1,8 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#define Q_NO_THREAD_STORAGE_TRIVIAL_WARNING
#include <QTest>
#if QT_CONFIG(process)
#include <QProcess>