From 07a15916cc3c42616251b8ce3345bd77f248d9d8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 8 Feb 2025 15:31:55 -0800 Subject: [PATCH] QThreadStorage: add a warning suggesting use of thread_local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Marc Mutz --- src/corelib/thread/qthreadstorage.h | 15 ++++++++++++++- .../qthreadstorage/crashonexit/crashOnExit.cpp | 1 + .../thread/qthreadstorage/tst_qthreadstorage.cpp | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h index 35ba0700796..32dc29f0c26 100644 --- a/src/corelib/thread/qthreadstorage.h +++ b/src/corelib/thread/qthreadstorage.h @@ -14,6 +14,18 @@ QT_BEGIN_NAMESPACE #if QT_CONFIG(thread) +template struct QThreadStorageTraits +{ + static constexpr void warnAboutTrivial() {} +}; +template <> struct QThreadStorageTraits +{ +#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 QThreadStorage { private: + using Trait = QThreadStorageTraits && !std::is_pointer_v>; QThreadStorageData d; Q_DISABLE_COPY(QThreadStorage) @@ -95,7 +108,7 @@ private: { qThreadStorage_deleteData(x, reinterpret_cast(0)); } public: - inline QThreadStorage() : d(deleteData) { } + inline QThreadStorage() : d(deleteData) { Trait::warnAboutTrivial(); } inline ~QThreadStorage() { } inline bool hasLocalData() const diff --git a/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashOnExit.cpp b/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashOnExit.cpp index 3b3a4d4813c..52dc5e22ac7 100644 --- a/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashOnExit.cpp +++ b/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashOnExit.cpp @@ -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 #include diff --git a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp index 0449909c889..e3734d27f7f 100644 --- a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp +++ b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp @@ -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 #if QT_CONFIG(process) #include