QMutexLocker: add move semantics
The class is similar to unique_lock in that it allows for unlocking and relocking. Since the locked state is tracked by QMutexLocker itself, it's trivial to make it movable. [ChangeLog][QtCore][QMutexLocker] The class is now movable. Change-Id: I534044f8024575e996c12efb2236761d493798a3 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
parent
4b8c20a297
commit
20d0ff1a39
@ -485,6 +485,40 @@ void QRecursiveMutex::unlock() noexcept
|
|||||||
\sa QMutex::lock()
|
\sa QMutex::lock()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\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
|
\fn template <typename Mutex> QMutexLocker<Mutex>::~QMutexLocker() noexcept
|
||||||
|
|
||||||
|
@ -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()
|
inline ~QMutexLocker()
|
||||||
{
|
{
|
||||||
unlock();
|
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
|
Mutex *mutex() const
|
||||||
{
|
{
|
||||||
return m_mutex;
|
return m_mutex;
|
||||||
|
@ -67,6 +67,7 @@ private slots:
|
|||||||
void scopeTest();
|
void scopeTest();
|
||||||
void unlockAndRelockTest();
|
void unlockAndRelockTest();
|
||||||
void lockerStateTest();
|
void lockerStateTest();
|
||||||
|
void moveSemantics();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_QMutexLocker::scopeTest()
|
void tst_QMutexLocker::scopeTest()
|
||||||
@ -214,5 +215,71 @@ void tst_QMutexLocker::lockerStateTest()
|
|||||||
thread = nullptr;
|
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)
|
QTEST_MAIN(tst_QMutexLocker)
|
||||||
#include "tst_qmutexlocker.moc"
|
#include "tst_qmutexlocker.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user