From 32eb742b04e57a71183524dc7e9aa51e262b95d7 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Fri, 11 Jun 2021 11:31:00 +0200 Subject: [PATCH] QOrderedMutexLocker: Disable copy and provide explicit dismiss function Copying a QOrderedMutexLocker is questionable, and would currenly easily lead to UB. Therefore we delete the copy ctor and copy assignment operator, and implement well-behaving move operators. In addition, provide an explicit dismiss method for cases where we don't want the locker to unlock the mutexes, as they have been manually unlocked (this could have been implemented previoulsy by using the copy assignment operator). Change-Id: If2a888710e1c74277b28fd3e2939ab26fff0c7ae Reviewed-by: Andrei Golubev Reviewed-by: Lars Knoll (cherry picked from commit 7fefce73284de4204d64c7e4129f39004a13cdad) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/thread/qorderedmutexlocker_p.h | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index abd9b56c94a..dfa45472ca6 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -74,6 +74,24 @@ public: { relock(); } + + Q_DISABLE_COPY(QOrderedMutexLocker) + + void swap(QOrderedMutexLocker &other) noexcept + { + qSwap(this->mtx1, other.mtx1); + qSwap(this->mtx2, other.mtx2); + qSwap(this->locked, other.locked); + } + + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QOrderedMutexLocker) + + QOrderedMutexLocker(QOrderedMutexLocker &&other) noexcept + : mtx1(std::exchange(other.mtx1, nullptr)) + , mtx2(std::exchange(other.mtx2, nullptr)) + , locked(std::exchange(other.locked, false)) + {} + ~QOrderedMutexLocker() { unlock(); @@ -88,6 +106,21 @@ public: } } + /*! + \internal + Can be called if the mutexes have been unlocked manually, and sets the + state of the QOrderedMutexLocker to unlocked. + The caller is expected to have unlocked both of them if they + are not the same. Calling this method when the QOrderedMutexLocker is + unlocked or when the provided mutexes have not actually been unlocked is + UB. + */ + void dismiss() + { + Q_ASSERT(locked); + locked = false; + } + void unlock() { if (locked) { @@ -153,11 +186,15 @@ private: class QOrderedMutexLocker { public: + Q_DISABLE_COPY(QOrderedMutexLocker) QOrderedMutexLocker(QBasicMutex *, QBasicMutex *) {} + QOrderedMutexLocker(QOrderedMutexLocker &&) = default; + QOrderedMutexLocker& operator=(QOrderedMutexLocker &&other) = default; ~QOrderedMutexLocker() {} void relock() {} void unlock() {} + void dismiss() {} static bool relock(QBasicMutex *, QBasicMutex *) { return false; } };