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:
parent
32ee5539fd
commit
38f77d09e8
@ -1119,9 +1119,9 @@ void QThread::setTerminationEnabled(bool)
|
|||||||
// No threads: so we can just use static variables
|
// No threads: so we can just use static variables
|
||||||
Q_CONSTINIT static QThreadData *data = nullptr;
|
Q_CONSTINIT static QThreadData *data = nullptr;
|
||||||
|
|
||||||
QThreadData *QThreadData::current(bool createIfNecessary)
|
QThreadData *QThreadData::current()
|
||||||
{
|
{
|
||||||
if (!data && createIfNecessary) {
|
if (!data) {
|
||||||
data = new QThreadData;
|
data = new QThreadData;
|
||||||
data->thread = new QAdoptedThread(data);
|
data->thread = new QAdoptedThread(data);
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ public:
|
|||||||
}
|
}
|
||||||
~QThreadData();
|
~QThreadData();
|
||||||
|
|
||||||
static Q_AUTOTEST_EXPORT QThreadData *current(bool createIfNecessary = true);
|
static Q_AUTOTEST_EXPORT QThreadData *current();
|
||||||
static void clearCurrentThreadData();
|
static void clearCurrentThreadData();
|
||||||
static QThreadData *get2(QThread *thread)
|
static QThreadData *get2(QThread *thread)
|
||||||
{ Q_ASSERT_X(thread != nullptr, "QThread", "internal error"); return thread->d_func()->data; }
|
{ Q_ASSERT_X(thread != nullptr, "QThread", "internal error"); return thread->d_func()->data; }
|
||||||
|
@ -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
|
// 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)
|
#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;
|
Q_CONSTINIT static thread_local QThreadData *currentThreadData = nullptr;
|
||||||
|
|
||||||
static void destroy_current_thread_data(void *p)
|
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)
|
Q_DESTRUCTOR_FUNCTION(destroy_main_thread_data)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void set_thread_data(QThreadData *data)
|
static void set_thread_data(QThreadData *data) noexcept
|
||||||
{
|
{
|
||||||
if (data) {
|
if (data) {
|
||||||
if constexpr (QT_CONFIG(broken_threadlocal_dtors)) {
|
if constexpr (QT_CONFIG(broken_threadlocal_dtors)) {
|
||||||
static pthread_key_t tls_key;
|
static pthread_key_t tls_key;
|
||||||
struct TlsKey {
|
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); }
|
~TlsKey() { pthread_key_delete(tls_key); }
|
||||||
};
|
};
|
||||||
static TlsKey currentThreadCleanup;
|
static TlsKey currentThreadCleanup;
|
||||||
@ -197,11 +196,6 @@ static void set_thread_data(QThreadData *data)
|
|||||||
currentThreadData = data;
|
currentThreadData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_thread_data()
|
|
||||||
{
|
|
||||||
set_thread_data(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static typename std::enable_if<std::is_integral_v<T>, Qt::HANDLE>::type to_HANDLE(T id)
|
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()
|
void QThreadData::clearCurrentThreadData()
|
||||||
{
|
{
|
||||||
clear_thread_data();
|
set_thread_data(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
QThreadData *QThreadData::current(bool createIfNecessary)
|
QThreadData *QThreadData::current()
|
||||||
{
|
{
|
||||||
QThreadData *data = get_thread_data();
|
if (QThreadData *data = get_thread_data(); Q_LIKELY(data))
|
||||||
if (!data && createIfNecessary) {
|
return data;
|
||||||
data = new QThreadData;
|
|
||||||
|
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 {
|
QT_TRY {
|
||||||
set_thread_data(data);
|
data->thread.storeRelease(new QAdoptedThread(data.get()));
|
||||||
data->thread.storeRelease(new QAdoptedThread(data));
|
|
||||||
} QT_CATCH(...) {
|
} QT_CATCH(...) {
|
||||||
clear_thread_data();
|
clearCurrentThreadData();
|
||||||
data->deref();
|
|
||||||
data = nullptr;
|
|
||||||
QT_RETHROW;
|
QT_RETHROW;
|
||||||
}
|
}
|
||||||
}
|
return data.release();
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QAdoptedThread::init()
|
void QAdoptedThread::init()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,12 @@ static void destroy_current_thread_data(void *p)
|
|||||||
currentThreadData = nullptr;
|
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) {
|
if (data) {
|
||||||
struct Cleanup {
|
struct Cleanup {
|
||||||
@ -91,24 +96,24 @@ void QThreadData::clearCurrentThreadData()
|
|||||||
set_thread_data(nullptr);
|
set_thread_data(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
QThreadData *QThreadData::current(bool createIfNecessary)
|
QThreadData *QThreadData::current()
|
||||||
{
|
{
|
||||||
QThreadData *threadData = currentThreadData;
|
if (QThreadData *data = get_thread_data(); Q_LIKELY(data))
|
||||||
if (!threadData && createIfNecessary) {
|
return data;
|
||||||
threadData = new QThreadData;
|
|
||||||
// This needs to be called prior to new AdoptedThread() to
|
std::unique_ptr data = std::make_unique<QThreadData>();
|
||||||
// avoid recursion.
|
|
||||||
set_thread_data(threadData);
|
// This needs to be called prior to new QAdoptedThread() to avoid
|
||||||
|
// recursion (see qobject.cpp).
|
||||||
|
set_thread_data(data.get());
|
||||||
|
|
||||||
QT_TRY {
|
QT_TRY {
|
||||||
threadData->thread.storeRelease(new QAdoptedThread(threadData));
|
data->thread.storeRelease(new QAdoptedThread(data.get()));
|
||||||
} QT_CATCH(...) {
|
} QT_CATCH(...) {
|
||||||
set_thread_data(nullptr);
|
clearCurrentThreadData();
|
||||||
threadData->deref();
|
|
||||||
threadData = 0;
|
|
||||||
QT_RETHROW;
|
QT_RETHROW;
|
||||||
}
|
}
|
||||||
}
|
return data.release();
|
||||||
return threadData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAdoptedThread::init()
|
void QAdoptedThread::init()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user