diff options
-rw-r--r-- | src/corelib/thread/qmutex.cpp | 34 | ||||
-rw-r--r-- | src/corelib/thread/qmutex.h | 13 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qmutexlocker/tst_qmutexlocker.cpp | 67 |
3 files changed, 114 insertions, 0 deletions
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index dec0a95c47..94e0fd25b1 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -486,6 +486,40 @@ void QRecursiveMutex::unlock() noexcept */ /*! + \fn template <typename Mutex> QMutexLocker<Mutex>::QMutexLocker(QMutexLocker &&other) noexcept + \since 6.4 + + Move-constructs a QMutexLocker from \a other. The mutex and the + state of \a other is transferred to the newly constructed instance. + After the move, \a other will no longer be managing its mutex. + + \sa QMutex::lock() +*/ + +/*! + \fn template <typename Mutex> QMutexLocker<Mutex> &QMutexLocker<Mutex>::operator=(QMutexLocker &&other) noexcept + \since 6.4 + + Move-assigns \a other onto this QMutexLocker. If this QMutexLocker + was holding a locked mutex before the assignment, the mutex will be + unlocked. The mutex and the state of \a other is then transferred + to this QMutexLocker. After the move, \a other will no longer be + managing its mutex. + + \sa QMutex::lock() +*/ + +/*! + \fn template <typename Mutex> void QMutexLocker<Mutex>::swap(QMutexLocker &other) noexcept + \since 6.4 + + Swaps the mutex and the state of this QMutexLocker with \a other. + This operation is very fast and never fails. + + \sa QMutex::lock() +*/ + +/*! \fn template <typename Mutex> QMutexLocker<Mutex>::~QMutexLocker() noexcept Destroys the QMutexLocker and unlocks the mutex that was locked diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index f57a95de22..e10a3f8f3d 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -247,6 +247,13 @@ public: } } + inline QMutexLocker(QMutexLocker &&other) noexcept + : m_mutex(std::exchange(other.m_mutex, nullptr)), + m_isLocked(std::exchange(other.m_isLocked, false)) + {} + + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QMutexLocker) + inline ~QMutexLocker() { unlock(); @@ -275,6 +282,12 @@ public: } } + inline void swap(QMutexLocker &other) noexcept + { + qt_ptr_swap(m_mutex, other.m_mutex); + std::swap(m_isLocked, other.m_isLocked); + } + Mutex *mutex() const { return m_mutex; diff --git a/tests/auto/corelib/thread/qmutexlocker/tst_qmutexlocker.cpp b/tests/auto/corelib/thread/qmutexlocker/tst_qmutexlocker.cpp index 29c8b92222..8844dd5624 100644 --- a/tests/auto/corelib/thread/qmutexlocker/tst_qmutexlocker.cpp +++ b/tests/auto/corelib/thread/qmutexlocker/tst_qmutexlocker.cpp @@ -67,6 +67,7 @@ private slots: void scopeTest(); void unlockAndRelockTest(); void lockerStateTest(); + void moveSemantics(); }; void tst_QMutexLocker::scopeTest() @@ -214,5 +215,71 @@ void tst_QMutexLocker::lockerStateTest() thread = nullptr; } +void tst_QMutexLocker::moveSemantics() +{ + { + QMutexLocker<QMutex> locker(nullptr); + QVERIFY(!locker.isLocked()); + QCOMPARE(locker.mutex(), nullptr); + + QMutexLocker locker2(std::move(locker)); + QVERIFY(!locker.isLocked()); + QVERIFY(!locker2.isLocked()); + QCOMPARE(locker.mutex(), nullptr); + QCOMPARE(locker2.mutex(), nullptr); + } + + QMutex mutex; + + { + QMutexLocker locker(&mutex); + QVERIFY(locker.isLocked()); + QCOMPARE(locker.mutex(), &mutex); + QVERIFY(!mutex.tryLock()); + + QMutexLocker locker2(std::move(locker)); + QVERIFY(!locker.isLocked()); + QVERIFY(locker2.isLocked()); + QCOMPARE(locker.mutex(), nullptr); + QCOMPARE(locker2.mutex(), &mutex); + QVERIFY(!mutex.tryLock()); + } + + QVERIFY(mutex.tryLock()); + mutex.unlock(); + + { + QMutex mutex; + QMutexLocker locker(&mutex); + QVERIFY(locker.isLocked()); + QCOMPARE(locker.mutex(), &mutex); + QVERIFY(!mutex.tryLock()); + + locker.unlock(); + QVERIFY(!locker.isLocked()); + QCOMPARE(locker.mutex(), &mutex); + QVERIFY(mutex.tryLock()); + mutex.unlock(); + + QMutexLocker locker2(std::move(locker)); + QVERIFY(!locker.isLocked()); + QVERIFY(!locker2.isLocked()); + QCOMPARE(locker.mutex(), nullptr); + QCOMPARE(locker2.mutex(), &mutex); + QVERIFY(mutex.tryLock()); + mutex.unlock(); + + locker2.relock(); + QVERIFY(!locker.isLocked()); + QVERIFY(locker2.isLocked()); + QCOMPARE(locker.mutex(), nullptr); + QCOMPARE(locker2.mutex(), &mutex); + QVERIFY(!mutex.tryLock()); + } + + QVERIFY(mutex.tryLock()); + mutex.unlock(); +} + QTEST_MAIN(tst_QMutexLocker) #include "tst_qmutexlocker.moc" |