diff options
Diffstat (limited to 'src/corelib/thread')
-rw-r--r-- | src/corelib/thread/qfutureinterface.cpp | 5 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.h | 13 | ||||
-rw-r--r-- | src/corelib/thread/qlocking_p.h | 119 | ||||
-rw-r--r-- | src/corelib/thread/qreadwritelock.h | 28 | ||||
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 23 | ||||
-rw-r--r-- | src/corelib/thread/qthread_win.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/thread.pri | 1 |
7 files changed, 150 insertions, 41 deletions
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp index 8f4cae8816..6430f38a3b 100644 --- a/src/corelib/thread/qfutureinterface.cpp +++ b/src/corelib/thread/qfutureinterface.cpp @@ -429,6 +429,11 @@ QMutex *QFutureInterfaceBase::mutex() const return &d->m_mutex; } +QMutex &QFutureInterfaceBase::mutex(int) const +{ + return d->m_mutex; +} + QtPrivate::ExceptionStore &QFutureInterfaceBase::exceptionStore() { return d->m_exceptionStore; diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h index d5e2401eee..bcdae24833 100644 --- a/src/corelib/thread/qfutureinterface.h +++ b/src/corelib/thread/qfutureinterface.h @@ -45,6 +45,8 @@ #include <QtCore/qexception.h> #include <QtCore/qresultstore.h> +#include <mutex> + QT_REQUIRE_CONFIG(future); QT_BEGIN_NAMESPACE @@ -118,6 +120,7 @@ public: void waitForResume(); QMutex *mutex() const; + QMutex &mutex(int) const; QtPrivate::ExceptionStore &exceptionStore(); QtPrivate::ResultStoreBase &resultStoreBase(); const QtPrivate::ResultStoreBase &resultStoreBase() const; @@ -188,7 +191,7 @@ public: template <typename T> inline void QFutureInterface<T>::reportResult(const T *result, int index) { - QMutexLocker locker(mutex()); + std::lock_guard<QMutex> locker(mutex(0)); if (this->queryState(Canceled) || this->queryState(Finished)) { return; } @@ -214,7 +217,7 @@ inline void QFutureInterface<T>::reportResult(const T &result, int index) template <typename T> inline void QFutureInterface<T>::reportResults(const QVector<T> &_results, int beginIndex, int count) { - QMutexLocker locker(mutex()); + std::lock_guard<QMutex> locker(mutex(0)); if (this->queryState(Canceled) || this->queryState(Finished)) { return; } @@ -242,14 +245,14 @@ inline void QFutureInterface<T>::reportFinished(const T *result) template <typename T> inline const T &QFutureInterface<T>::resultReference(int index) const { - QMutexLocker lock(mutex()); + std::lock_guard<QMutex> locker(mutex(0)); return resultStoreBase().resultAt(index).template value<T>(); } template <typename T> inline const T *QFutureInterface<T>::resultPointer(int index) const { - QMutexLocker lock(mutex()); + std::lock_guard<QMutex> locker(mutex(0)); return resultStoreBase().resultAt(index).template pointer<T>(); } @@ -263,7 +266,7 @@ inline QList<T> QFutureInterface<T>::results() QFutureInterfaceBase::waitForResult(-1); QList<T> res; - QMutexLocker lock(mutex()); + std::lock_guard<QMutex> locker(mutex(0)); QtPrivate::ResultIteratorBase it = resultStoreBase().begin(); while (it != resultStoreBase().end()) { diff --git a/src/corelib/thread/qlocking_p.h b/src/corelib/thread/qlocking_p.h new file mode 100644 index 0000000000..9a796cf7f7 --- /dev/null +++ b/src/corelib/thread/qlocking_p.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOCKING_P_H +#define QLOCKING_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qmutex.cpp, qmutex_unix.cpp, and qmutex_win.cpp. This header +// file may change from version to version without notice, or even be +// removed. +// +// We mean it. +// + +#include <QtCore/qmutex.h> + +#include <mutex> + +QT_BEGIN_NAMESPACE + +// +// This API is bridging the time until we can depend on C++17: +// +// - qt_scoped_lock returns a lock that cannot be unlocked again before the end of the scope +// - qt_unique_lock returns a lock that can be unlock()ed and moved around +// - for compat with QMutexLocker, qt_unique_lock supports passing by pointer. +// Do NOT use this overload lightly; it's only for cases such as where a Q_GLOBAL_STATIC +// may have already been deleted. In particular, do NOT port from +// QMutexLocker locker(&mutex); +// to +// auto locker = qt_unique_lock(&mutex); +// as this will not port automatically to std::unique_lock come C++17! +// +// The intent, come C++17, is to replace +// qt_scoped_lock(mutex); +// qt_unique_lock(mutex); // except qt_unique_lock(&mutex) +// with +// std::scoped_lock(mutex); +// std::unique_lock(mutex); +// resp. (C++17 meaning CTAD, guaranteed copy elision + scoped_lock available on all platforms), +// so please use these functions only in ways which don't break this mechanical search & replace. +// + +namespace { + +template <typename Mutex, typename Lock = +#if defined(__cpp_guaranteed_copy_elision) && __cpp_guaranteed_copy_elision >= 201606L +# if defined(__cpp_lib_scoped_lock) && __cpp_lib_scoped_lock >= 201703L + std::scoped_lock +# else + std::lock_guard +# endif +#else + std::unique_lock +#endif + <typename std::decay<Mutex>::type> +> +Lock qt_scoped_lock(Mutex &mutex) +{ + return Lock(mutex); +} + +template <typename Mutex, typename Lock = std::unique_lock<typename std::decay<Mutex>::type>> +Lock qt_unique_lock(Mutex &mutex) +{ + return Lock(mutex); +} + +template <typename Mutex, typename Lock = std::unique_lock<typename std::decay<Mutex>::type>> +Lock qt_unique_lock(Mutex *mutex) +{ + return mutex ? Lock(*mutex) : Lock() ; +} + +} // unnamed namespace + +QT_END_NAMESPACE + +#endif // QLOCKING_P_H diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h index 139fde9214..3c1ed91b94 100644 --- a/src/corelib/thread/qreadwritelock.h +++ b/src/corelib/thread/qreadwritelock.h @@ -183,15 +183,15 @@ public: inline explicit QReadWriteLock(RecursionMode = NonRecursive) noexcept { } inline ~QReadWriteLock() { } - static inline void lockForRead() noexcept { } - static inline bool tryLockForRead() noexcept { return true; } - static inline bool tryLockForRead(int timeout) noexcept { Q_UNUSED(timeout); return true; } + void lockForRead() noexcept { } + bool tryLockForRead() noexcept { return true; } + bool tryLockForRead(int timeout) noexcept { Q_UNUSED(timeout); return true; } - static inline void lockForWrite() noexcept { } - static inline bool tryLockForWrite() noexcept { return true; } - static inline bool tryLockForWrite(int timeout) noexcept { Q_UNUSED(timeout); return true; } + void lockForWrite() noexcept { } + bool tryLockForWrite() noexcept { return true; } + bool tryLockForWrite(int timeout) noexcept { Q_UNUSED(timeout); return true; } - static inline void unlock() noexcept { } + void unlock() noexcept { } private: Q_DISABLE_COPY(QReadWriteLock) @@ -200,12 +200,12 @@ private: class Q_CORE_EXPORT QReadLocker { public: - inline QReadLocker(QReadWriteLock *) noexcept { } + inline explicit QReadLocker(QReadWriteLock *) noexcept { } inline ~QReadLocker() noexcept { } - static inline void unlock() noexcept { } - static inline void relock() noexcept { } - static inline QReadWriteLock *readWriteLock() noexcept { return nullptr; } + void unlock() noexcept { } + void relock() noexcept { } + QReadWriteLock *readWriteLock() noexcept { return nullptr; } private: Q_DISABLE_COPY(QReadLocker) @@ -217,9 +217,9 @@ public: inline explicit QWriteLocker(QReadWriteLock *) noexcept { } inline ~QWriteLocker() noexcept { } - static inline void unlock() noexcept { } - static inline void relock() noexcept { } - static inline QReadWriteLock *readWriteLock() noexcept { return nullptr; } + void unlock() noexcept { } + void relock() noexcept { } + QReadWriteLock *readWriteLock() noexcept { return nullptr; } private: Q_DISABLE_COPY(QWriteLocker) diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 38e9c1c3ec..cb3c0d6bb1 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -108,20 +108,8 @@ Q_STATIC_ASSERT(sizeof(pthread_t) <= sizeof(Qt::HANDLE)); enum { ThreadPriorityResetFlag = 0x80000000 }; -#if defined(Q_OS_LINUX) && defined(__GLIBC__) && (defined(Q_CC_GNU) || defined(Q_CC_INTEL)) && !defined(QT_LINUXBASE) -/* LSB doesn't have __thread, https://lsbbugs.linuxfoundation.org/show_bug.cgi?id=993 */ -#define HAVE_TLS -#endif -#if defined(Q_CC_XLC) || defined (Q_CC_SUN) -#define HAVE_TLS -#endif -#if defined(Q_OS_RTEMS) -#define HAVE_TLS -#endif -#ifdef HAVE_TLS -static __thread QThreadData *currentThreadData = 0; -#endif +static thread_local QThreadData *currentThreadData = 0; static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT; static pthread_key_t current_thread_data_key; @@ -182,28 +170,19 @@ Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key) // Utility functions for getting, setting and clearing thread specific data. static QThreadData *get_thread_data() { -#ifdef HAVE_TLS return currentThreadData; -#else - pthread_once(¤t_thread_data_once, create_current_thread_data_key); - return reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key)); -#endif } static void set_thread_data(QThreadData *data) { -#ifdef HAVE_TLS currentThreadData = data; -#endif pthread_once(¤t_thread_data_once, create_current_thread_data_key); pthread_setspecific(current_thread_data_key, data); } static void clear_thread_data() { -#ifdef HAVE_TLS currentThreadData = 0; -#endif pthread_setspecific(current_thread_data_key, 0); } diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index f8a0b0abaa..a72df2fc40 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -99,6 +99,8 @@ void qt_create_tls() return; static QBasicMutex mutex; QMutexLocker locker(&mutex); + if (qt_current_thread_data_tls_index != TLS_OUT_OF_INDEXES) + return; qt_current_thread_data_tls_index = TlsAlloc(); } diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index d11e6500ff..9fc9af0e65 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -28,6 +28,7 @@ qtConfig(thread) { thread/qbasicatomic.h \ thread/qfutex_p.h \ thread/qgenericatomic.h \ + thread/qlocking_p.h \ thread/qmutex_p.h \ thread/qorderedmutexlocker_p.h \ thread/qreadwritelock_p.h \ |