diff options
Diffstat (limited to 'src/corelib/thread')
-rw-r--r-- | src/corelib/thread/qfuture.h | 25 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.h | 10 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface_p.h | 1 | ||||
-rw-r--r-- | src/corelib/thread/qmutex.cpp | 55 | ||||
-rw-r--r-- | src/corelib/thread/qmutex.h | 57 | ||||
-rw-r--r-- | src/corelib/thread/qmutex_p.h | 2 | ||||
-rw-r--r-- | src/corelib/thread/qmutex_win.cpp | 4 | ||||
-rw-r--r-- | src/corelib/thread/qmutexpool_p.h | 5 | ||||
-rw-r--r-- | src/corelib/thread/qorderedmutexlocker_p.h | 1 | ||||
-rw-r--r-- | src/corelib/thread/qreadwritelock_p.h | 2 | ||||
-rw-r--r-- | src/corelib/thread/qthread.cpp | 4 | ||||
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 4 | ||||
-rw-r--r-- | src/corelib/thread/qthread_win.cpp | 44 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition.h | 3 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition.qdoc | 15 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition_win.cpp | 5 |
16 files changed, 163 insertions, 74 deletions
diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h index 7ae5c68bb9..1f0c747f40 100644 --- a/src/corelib/thread/qfuture.h +++ b/src/corelib/thread/qfuture.h @@ -65,13 +65,7 @@ public: explicit QFuture(QFutureInterface<T> *p) // internal : d(*p) { } - QFuture(const QFuture &other) - : d(other.d) - { } - ~QFuture() - { } - inline QFuture &operator=(const QFuture &other); bool operator==(const QFuture &other) const { return (d == other.d); } bool operator!=(const QFuture &other) const { return (d != other.d); } @@ -157,13 +151,6 @@ public: // Warning: the d pointer is not documented and is considered private. }; template <typename T> -inline QFuture<T> &QFuture<T>::operator=(const QFuture<T> &other) -{ - d = other.d; - return *this; -} - -template <typename T> inline T QFuture<T>::result() const { d.waitForResult(0); @@ -195,13 +182,7 @@ public: explicit QFuture(QFutureInterfaceBase *p) // internal : d(*p) { } - QFuture(const QFuture &other) - : d(other.d) - { } - ~QFuture() - { } - QFuture &operator=(const QFuture &other); bool operator==(const QFuture &other) const { return (d == other.d); } bool operator!=(const QFuture &other) const { return (d != other.d); } @@ -248,12 +229,6 @@ public: mutable QFutureInterfaceBase d; }; -inline QFuture<void> &QFuture<void>::operator=(const QFuture<void> &other) -{ - d = other.d; - return *this; -} - inline QFuture<void> QFutureInterface<void>::future() { return QFuture<void>(this); diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h index 1787ff3b93..559d26e231 100644 --- a/src/corelib/thread/qfutureinterface.h +++ b/src/corelib/thread/qfutureinterface.h @@ -285,21 +285,13 @@ template <> class QFutureInterface<void> : public QFutureInterfaceBase { public: - QFutureInterface<void>(State initialState = NoState) + explicit QFutureInterface<void>(State initialState = NoState) : QFutureInterfaceBase(initialState) { } - QFutureInterface<void>(const QFutureInterface<void> &other) - : QFutureInterfaceBase(other) - { } static QFutureInterface<void> canceledResult() { return QFutureInterface(State(Started | Finished | Canceled)); } - QFutureInterface<void> &operator=(const QFutureInterface<void> &other) - { - QFutureInterfaceBase::operator=(other); - return *this; - } inline QFuture<void> future(); // implemented in qfuture.h diff --git a/src/corelib/thread/qfutureinterface_p.h b/src/corelib/thread/qfutureinterface_p.h index f5f0e7047f..ee8dfe1354 100644 --- a/src/corelib/thread/qfutureinterface_p.h +++ b/src/corelib/thread/qfutureinterface_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtCore/private/qglobal_p.h> #include <QtCore/qelapsedtimer.h> #include <QtCore/qcoreevent.h> #include <QtCore/qlist.h> diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 878a920ffc..366413e82e 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -264,6 +264,61 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT return lockInternal(timeout); } +/*! \fn bool QMutex::try_lock() + \since 5.8 + + This function is provided for compatibility with the Standard Library + concept \c Lockable. It is equivalent to tryLock(). +*/ + +/*! \fn bool QMutex::try_lock_for(std::chrono::duration<Rep, Period> duration) + \since 5.8 + + Attempts to lock the mutex. This function returns \c true if the lock + was obtained; otherwise it returns \c false. If another thread has + locked the mutex, this function will wait for at most \a duration + for the mutex to become available. + + Note: Passing a negative duration as the \a duration is equivalent to + calling try_lock(). This behavior is different from tryLock. + + If the lock was obtained, the mutex must be unlocked with unlock() + before another thread can successfully lock it. + + Calling this function multiple times on the same mutex from the + same thread is allowed if this mutex is a + \l{QMutex::Recursive}{recursive mutex}. If this mutex is a + \l{QMutex::NonRecursive}{non-recursive mutex}, this function will + \e always return false when attempting to lock the mutex + recursively. + + \sa lock(), unlock() +*/ + +/*! \fn bool QMutex::try_lock_until(std::chrono::time_point<Clock, Duration> timePoint) + \since 5.8 + + Attempts to lock the mutex. This function returns \c true if the lock + was obtained; otherwise it returns \c false. If another thread has + locked the mutex, this function will wait at most until \a timePoint + for the mutex to become available. + + Note: Passing a \a timePoint which has already passed is equivalent + to calling try_lock. This behavior is different from tryLock. + + If the lock was obtained, the mutex must be unlocked with unlock() + before another thread can successfully lock it. + + Calling this function multiple times on the same mutex from the + same thread is allowed if this mutex is a + \l{QMutex::Recursive}{recursive mutex}. If this mutex is a + \l{QMutex::NonRecursive}{non-recursive mutex}, this function will + \e always return false when attempting to lock the mutex + recursively. + + \sa lock(), unlock() +*/ + /*! \fn void QMutex::unlock() Unlocks the mutex. Attempting to unlock a mutex in a different thread to the one that locked it results in an error. Unlocking a diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index a06bcd99ac..3a0e22e3bd 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -44,6 +44,10 @@ #include <QtCore/qatomic.h> #include <new> +#if QT_HAS_INCLUDE(<chrono>) +# include <chrono> +#endif + QT_BEGIN_NAMESPACE @@ -60,11 +64,13 @@ class QMutexData; class Q_CORE_EXPORT QBasicMutex { public: + // BasicLockable concept inline void lock() QT_MUTEX_LOCK_NOEXCEPT { if (!fastTryLock()) lockInternal(); } + // BasicLockable concept inline void unlock() Q_DECL_NOTHROW { Q_ASSERT(d_ptr.load()); //mutex must be locked if (!fastTryUnlock()) @@ -75,6 +81,9 @@ public: return fastTryLock(); } + // Lockable concept + bool try_lock() Q_DECL_NOTHROW { return tryLock(); } + bool isRecursive() Q_DECL_NOTHROW; //### Qt6: remove me bool isRecursive() const Q_DECL_NOTHROW; @@ -112,10 +121,41 @@ public: explicit QMutex(RecursionMode mode = NonRecursive); ~QMutex(); + // BasicLockable concept void lock() QT_MUTEX_LOCK_NOEXCEPT; bool tryLock(int timeout = 0) QT_MUTEX_LOCK_NOEXCEPT; + // BasicLockable concept void unlock() Q_DECL_NOTHROW; + // Lockable concept + bool try_lock() QT_MUTEX_LOCK_NOEXCEPT { return tryLock(); } + +#if QT_HAS_INCLUDE(<chrono>) + // TimedLockable concept + template <class Rep, class Period> + bool try_lock_for(std::chrono::duration<Rep, Period> duration) + { + // N4606 § 30.4.1.3 [thread.timedmutex.requirements]/5 specifies that + // a duration less than or equal to duration.zero() shall result in a + // try_lock, unlike QMutex's tryLock with a negative duration which + // results in a lock. + + if (duration <= duration.zero()) + return tryLock(0); + return tryLock(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count()); + } + + // TimedLockable concept + template<class Clock, class Duration> + bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint) + { + // Implemented in terms of try_lock_for to honor the similar + // requirement in N4606 § 30.4.1.3 [thread.timedmutex.requirements]/12. + + return try_lock_for(timePoint - Clock::now()); + } +#endif + bool isRecursive() const Q_DECL_NOTHROW { return QBasicMutex::isRecursive(); } @@ -189,9 +229,26 @@ public: inline void lock() Q_DECL_NOTHROW {} inline bool tryLock(int timeout = 0) Q_DECL_NOTHROW { Q_UNUSED(timeout); return true; } + inline bool try_lock() Q_DECL_NOTHROW { return true; } inline void unlock() Q_DECL_NOTHROW {} inline bool isRecursive() const Q_DECL_NOTHROW { return true; } +#if QT_HAS_INCLUDE(<chrono>) || defined(Q_QDOC) + template <class Rep, class Period> + inline bool try_lock_for(std::chrono::duration<Rep, Period> duration) Q_DECL_NOTHROW + { + Q_UNUSED(duration); + return true; + } + + template<class Clock, class Duration> + inline bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint) Q_DECL_NOTHROW + { + Q_UNUSED(timePoint); + return true; + } +#endif + private: Q_DISABLE_COPY(QMutex) }; diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h index 20cc5f1f5e..4e6f522a37 100644 --- a/src/corelib/thread/qmutex_p.h +++ b/src/corelib/thread/qmutex_p.h @@ -54,7 +54,7 @@ // We mean it. // -#include <QtCore/qglobal.h> +#include <QtCore/private/qglobal_p.h> #include <QtCore/qnamespace.h> #include <QtCore/qmutex.h> #include <QtCore/qatomic.h> diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index acb0f9dc61..3c314a4c0c 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -61,11 +61,7 @@ QMutexPrivate::~QMutexPrivate() bool QMutexPrivate::wait(int timeout) { -#ifndef Q_OS_WINCE return (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0); -#else - return (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0); -#endif } void QMutexPrivate::wakeUp() Q_DECL_NOTHROW diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h index 796e65d960..58d853b0e3 100644 --- a/src/corelib/thread/qmutexpool_p.h +++ b/src/corelib/thread/qmutexpool_p.h @@ -44,13 +44,14 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists for the convenience -// of QSettings. This header file may change from version to +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // +#include <QtCore/private/qglobal_p.h> #include "QtCore/qatomic.h" #include "QtCore/qmutex.h" #include "QtCore/qvarlengtharray.h" diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index f54f7c705d..81c7c5268c 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtCore/private/qglobal_p.h> #include <QtCore/qmutex.h> #include <functional> diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h index 24d25eb2be..bb58dfab56 100644 --- a/src/corelib/thread/qreadwritelock_p.h +++ b/src/corelib/thread/qreadwritelock_p.h @@ -52,7 +52,7 @@ // We mean it. // -#include <QtCore/qglobal.h> +#include <QtCore/private/qglobal_p.h> #include <QtCore/qhash.h> #include <QtCore/QWaitCondition> diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 4aac24f454..7118ad5c9b 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -403,7 +403,7 @@ QThread::QThread(QThreadPrivate &dd, QObject *parent) Note that deleting a QThread object will not stop the execution of the thread it manages. Deleting a running QThread (i.e. - isFinished() returns \c false) will probably result in a program + isFinished() returns \c false) will result in a program crash. Wait for the finished() signal before deleting the QThread. */ @@ -418,7 +418,7 @@ QThread::~QThread() locker.relock(); } if (d->running && !d->finished && !d->data->isAdopted) - qWarning("QThread: Destroyed while thread is still running"); + qFatal("QThread: Destroyed while thread is still running"); d->data->thread = 0; } diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index deedd61c17..ba5f2dca95 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -45,7 +45,7 @@ #include <private/qcoreapplication_p.h> #include <private/qcore_unix_p.h> -#if defined(Q_OS_OSX) +#if defined(Q_OS_DARWIN) # include <private/qeventdispatcher_cf_p.h> #else # if !defined(QT_NO_GLIB) @@ -279,7 +279,7 @@ typedef void*(*QtThreadCallback)(void*); void QThreadPrivate::createEventDispatcher(QThreadData *data) { -#if defined(Q_OS_OSX) +#if defined(Q_OS_DARWIN) bool ok = false; int value = qEnvironmentVariableIntValue("QT_EVENT_DISPATCHER_CORE_FOUNDATION", &ok); if (ok && value > 0) diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index ef1799a021..a14c193bad 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -55,15 +55,10 @@ #include <qt_windows.h> #ifndef Q_OS_WINRT -#ifndef Q_OS_WINCE -#ifndef _MT -#define _MT -#endif // _MT -#include <process.h> -#else // !Q_OS_WINCE -#include "qfunctions_wince.h" -#endif // Q_OS_WINCE -#else // !Q_OS_WINRT +# ifndef _MT +# define _MT +# endif // _MT +# include <process.h> #endif // Q_OS_WINRT #ifndef QT_NO_THREAD @@ -150,7 +145,6 @@ QThreadData *QThreadData::current(bool createIfNecessary) // WinRT API? } else { HANDLE realHandle = INVALID_HANDLE_VALUE; -#if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600)) DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), @@ -158,9 +152,6 @@ QThreadData *QThreadData::current(bool createIfNecessary) 0, FALSE, DUPLICATE_SAME_ACCESS); -#else - realHandle = reinterpret_cast<HANDLE>(GetCurrentThreadId()); -#endif qt_watch_adopted_thread(realHandle, threadData->thread); } } @@ -190,9 +181,7 @@ void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread) QMutexLocker lock(&qt_adopted_thread_watcher_mutex); if (GetCurrentThreadId() == qt_adopted_thread_watcher_id) { -#if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600)) CloseHandle(adoptedThreadHandle); -#endif return; } @@ -291,9 +280,7 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID) data->deref(); QMutexLocker lock(&qt_adopted_thread_watcher_mutex); -#if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600)) CloseHandle(qt_adopted_thread_handles.at(handleIndex)); -#endif qt_adopted_thread_handles.remove(handleIndex); qt_adopted_qthreads.remove(qthreadIndex); } @@ -306,7 +293,7 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID) return 0; } -#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINRT) #ifndef Q_OS_WIN64 # define ULONG_PTR DWORD @@ -336,7 +323,7 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) { } } -#endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE && !Q_OS_WINRT +#endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINRT /************************************************************************** ** QThreadPrivate @@ -378,7 +365,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi else createEventDispatcher(data); -#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINRT) // sets the name of the current thread. QByteArray objectName = thr->objectName().toLocal8Bit(); qt_set_thread_name((HANDLE)-1, @@ -453,7 +440,7 @@ int QThread::idealThreadCount() Q_DECL_NOTHROW void QThread::yieldCurrentThread() { -#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +#if !defined(Q_OS_WINRT) SwitchToThread(); #else ::Sleep(0); @@ -495,7 +482,6 @@ void QThread::start(Priority priority) d->returnCode = 0; d->interruptionRequested = false; -#ifndef Q_OS_WINRT /* NOTE: we create the thread in the suspended state, set the priority and then resume the thread. @@ -506,9 +492,21 @@ void QThread::start(Priority priority) less than NormalPriority), but the newly created thread preempts its 'parent' and runs at normal priority. */ +#if defined(Q_CC_MSVC) && !defined(_DLL) // && !defined(Q_OS_WINRT) +# ifdef Q_OS_WINRT + // If you wish to accept the memory leaks, uncomment the part above. + // See: + // https://support.microsoft.com/en-us/kb/104641 + // https://msdn.microsoft.com/en-us/library/kdzttdcb.aspx +# error "Microsoft documentation says this combination leaks memory every time a thread is started. " \ + "Please change your build back to -MD/-MDd or, if you understand this issue and want to continue, " \ + "edit this source file." +# endif + // MSVC -MT or -MTd build d->handle = (Qt::HANDLE) _beginthreadex(NULL, d->stackSize, QThreadPrivate::start, this, CREATE_SUSPENDED, &(d->id)); -#else // !Q_OS_WINRT +#else + // MSVC -MD or -MDd or MinGW build d->handle = (Qt::HANDLE) CreateThread(NULL, d->stackSize, (LPTHREAD_START_ROUTINE)QThreadPrivate::start, this, CREATE_SUSPENDED, reinterpret_cast<LPDWORD>(&d->id)); #endif // Q_OS_WINRT diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h index d2e018834a..a0c6766833 100644 --- a/src/corelib/thread/qwaitcondition.h +++ b/src/corelib/thread/qwaitcondition.h @@ -65,6 +65,9 @@ public: void wakeOne(); void wakeAll(); + void notify_one() { wakeOne(); } + void notify_all() { wakeAll(); } + private: Q_DISABLE_COPY(QWaitCondition) diff --git a/src/corelib/thread/qwaitcondition.qdoc b/src/corelib/thread/qwaitcondition.qdoc index d7de323922..eebc28f059 100644 --- a/src/corelib/thread/qwaitcondition.qdoc +++ b/src/corelib/thread/qwaitcondition.qdoc @@ -172,3 +172,18 @@ \sa wakeOne(), wakeAll() */ + + +/*! \fn void QWaitCondition::notify_one() + \since 5.8 + + This function is provided for STL compatibility. It is equivalent + to wakeOne(). +*/ + +/*! \fn void QWaitCondition::notify_all() + \since 5.8 + + This function is provided for STL compatibility. It is equivalent + to wakeAll(). +*/ diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index a95ca0b8fd..e6610f18c8 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -115,12 +115,7 @@ bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, unsigned long time) { // wait for the event bool ret = false; -#ifndef Q_OS_WINCE switch (WaitForSingleObjectEx(wce->event, time, FALSE)) { -#else - switch (WaitForSingleObject(wce->event, time)) { -#endif - default: break; case WAIT_OBJECT_0: |