QThreadData: refactor current() now that it never returns null

Simplying the body of the function to rely less on the exception
handling too. The implementations for Unix and Windows are now literally
identical, but duplicated because they call different static functions

Change-Id: Ia14910a1c778ff5e606afffdabb8035e4603edda
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Thiago Macieira 2024-11-14 15:10:06 -07:00
parent 32ee5539fd
commit 38f77d09e8
4 changed files with 45 additions and 45 deletions

View File

@ -1119,9 +1119,9 @@ void QThread::setTerminationEnabled(bool)
// No threads: so we can just use static variables
Q_CONSTINIT static QThreadData *data = nullptr;
QThreadData *QThreadData::current(bool createIfNecessary)
QThreadData *QThreadData::current()
{
if (!data && createIfNecessary) {
if (!data) {
data = new QThreadData;
data->thread = new QAdoptedThread(data);
}

View File

@ -308,7 +308,7 @@ public:
}
~QThreadData();
static Q_AUTOTEST_EXPORT QThreadData *current(bool createIfNecessary = true);
static Q_AUTOTEST_EXPORT QThreadData *current();
static void clearCurrentThreadData();
static QThreadData *get2(QThread *thread)
{ Q_ASSERT_X(thread != nullptr, "QThread", "internal error"); return thread->d_func()->data; }

View File

@ -124,7 +124,6 @@ int pthread_timedjoin_np(...) { return ENOSYS; } // pretend
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/libcxxabi/src/cxa_thread_atexit.cpp#L118-L120
#endif // QT_CONFIG(broken_threadlocal_dtors)
// Always access this through the {get,set,clear}_thread_data() functions.
Q_CONSTINIT static thread_local QThreadData *currentThreadData = nullptr;
static void destroy_current_thread_data(void *p)
@ -176,13 +175,13 @@ static void destroy_main_thread_data()
Q_DESTRUCTOR_FUNCTION(destroy_main_thread_data)
#endif
static void set_thread_data(QThreadData *data)
static void set_thread_data(QThreadData *data) noexcept
{
if (data) {
if constexpr (QT_CONFIG(broken_threadlocal_dtors)) {
static pthread_key_t tls_key;
struct TlsKey {
TlsKey() { pthread_key_create(&tls_key, destroy_current_thread_data); }
TlsKey() noexcept { pthread_key_create(&tls_key, destroy_current_thread_data); }
~TlsKey() { pthread_key_delete(tls_key); }
};
static TlsKey currentThreadCleanup;
@ -197,11 +196,6 @@ static void set_thread_data(QThreadData *data)
currentThreadData = data;
}
static void clear_thread_data()
{
set_thread_data(nullptr);
}
template <typename T>
static typename std::enable_if<std::is_integral_v<T>, Qt::HANDLE>::type to_HANDLE(T id)
{
@ -228,28 +222,29 @@ static typename std::enable_if<std::is_pointer_v<T>, T>::type from_HANDLE(Qt::HA
void QThreadData::clearCurrentThreadData()
{
clear_thread_data();
set_thread_data(nullptr);
}
QThreadData *QThreadData::current(bool createIfNecessary)
QThreadData *QThreadData::current()
{
QThreadData *data = get_thread_data();
if (!data && createIfNecessary) {
data = new QThreadData;
if (QThreadData *data = get_thread_data(); Q_LIKELY(data))
return data;
std::unique_ptr data = std::make_unique<QThreadData>();
// This needs to be called prior to new QAdoptedThread() to avoid
// recursion (see qobject.cpp).
set_thread_data(data.get());
QT_TRY {
set_thread_data(data);
data->thread.storeRelease(new QAdoptedThread(data));
data->thread.storeRelease(new QAdoptedThread(data.get()));
} QT_CATCH(...) {
clear_thread_data();
data->deref();
data = nullptr;
clearCurrentThreadData();
QT_RETHROW;
}
}
return data;
return data.release();
}
void QAdoptedThread::init()
{
}

View File

@ -72,7 +72,12 @@ static void destroy_current_thread_data(void *p)
currentThreadData = nullptr;
}
static void set_thread_data(QThreadData *data)
static QThreadData *get_thread_data()
{
return currentThreadData;
}
static void set_thread_data(QThreadData *data) noexcept
{
if (data) {
struct Cleanup {
@ -91,24 +96,24 @@ void QThreadData::clearCurrentThreadData()
set_thread_data(nullptr);
}
QThreadData *QThreadData::current(bool createIfNecessary)
QThreadData *QThreadData::current()
{
QThreadData *threadData = currentThreadData;
if (!threadData && createIfNecessary) {
threadData = new QThreadData;
// This needs to be called prior to new AdoptedThread() to
// avoid recursion.
set_thread_data(threadData);
if (QThreadData *data = get_thread_data(); Q_LIKELY(data))
return data;
std::unique_ptr data = std::make_unique<QThreadData>();
// This needs to be called prior to new QAdoptedThread() to avoid
// recursion (see qobject.cpp).
set_thread_data(data.get());
QT_TRY {
threadData->thread.storeRelease(new QAdoptedThread(threadData));
data->thread.storeRelease(new QAdoptedThread(data.get()));
} QT_CATCH(...) {
set_thread_data(nullptr);
threadData->deref();
threadData = 0;
clearCurrentThreadData();
QT_RETHROW;
}
}
return threadData;
return data.release();
}
void QAdoptedThread::init()