Q(Basic)Mutex: add try_lock{,_for,_until} for STL compatibility
Now QBasicMutex is Lockable and QMutex is TimedLockable, which means they can be used in std::lock_guard, std::unique_lock, std::lock, etc. [ChangeLog][QtCore][QMutex] QMutex now fully models the TimedLockable concept by providing the try_lock, try_lock_for and try_lock_until functions, therefore making it usable in Standard Library lock management classes and functions. Change-Id: I7c691481a5781a696701e1ab78186b5cefbd6a87 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
parent
a8cf3b0257
commit
a594f85d54
@ -264,6 +264,61 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
|
|||||||
return lockInternal(timeout);
|
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()
|
/*! \fn void QMutex::unlock()
|
||||||
Unlocks the mutex. Attempting to unlock a mutex in a different
|
Unlocks the mutex. Attempting to unlock a mutex in a different
|
||||||
thread to the one that locked it results in an error. Unlocking a
|
thread to the one that locked it results in an error. Unlocking a
|
||||||
|
@ -44,6 +44,10 @@
|
|||||||
#include <QtCore/qatomic.h>
|
#include <QtCore/qatomic.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
#if QT_HAS_INCLUDE(<chrono>)
|
||||||
|
# include <chrono>
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
@ -60,11 +64,13 @@ class QMutexData;
|
|||||||
class Q_CORE_EXPORT QBasicMutex
|
class Q_CORE_EXPORT QBasicMutex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// BasicLockable concept
|
||||||
inline void lock() QT_MUTEX_LOCK_NOEXCEPT {
|
inline void lock() QT_MUTEX_LOCK_NOEXCEPT {
|
||||||
if (!fastTryLock())
|
if (!fastTryLock())
|
||||||
lockInternal();
|
lockInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BasicLockable concept
|
||||||
inline void unlock() Q_DECL_NOTHROW {
|
inline void unlock() Q_DECL_NOTHROW {
|
||||||
Q_ASSERT(d_ptr.load()); //mutex must be locked
|
Q_ASSERT(d_ptr.load()); //mutex must be locked
|
||||||
if (!fastTryUnlock())
|
if (!fastTryUnlock())
|
||||||
@ -75,6 +81,9 @@ public:
|
|||||||
return fastTryLock();
|
return fastTryLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lockable concept
|
||||||
|
bool try_lock() Q_DECL_NOTHROW { return tryLock(); }
|
||||||
|
|
||||||
bool isRecursive() Q_DECL_NOTHROW; //### Qt6: remove me
|
bool isRecursive() Q_DECL_NOTHROW; //### Qt6: remove me
|
||||||
bool isRecursive() const Q_DECL_NOTHROW;
|
bool isRecursive() const Q_DECL_NOTHROW;
|
||||||
|
|
||||||
@ -112,10 +121,41 @@ public:
|
|||||||
explicit QMutex(RecursionMode mode = NonRecursive);
|
explicit QMutex(RecursionMode mode = NonRecursive);
|
||||||
~QMutex();
|
~QMutex();
|
||||||
|
|
||||||
|
// BasicLockable concept
|
||||||
void lock() QT_MUTEX_LOCK_NOEXCEPT;
|
void lock() QT_MUTEX_LOCK_NOEXCEPT;
|
||||||
bool tryLock(int timeout = 0) QT_MUTEX_LOCK_NOEXCEPT;
|
bool tryLock(int timeout = 0) QT_MUTEX_LOCK_NOEXCEPT;
|
||||||
|
// BasicLockable concept
|
||||||
void unlock() Q_DECL_NOTHROW;
|
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)
|
||||||
|
{
|
||||||
|
// § 30.4.1.3.5 [thread.timedmutex.requirements] 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 § 30.4.1.3.12 [thread.timedmutex.requirements]
|
||||||
|
|
||||||
|
return try_lock_for(timePoint - Clock::now());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool isRecursive() const Q_DECL_NOTHROW
|
bool isRecursive() const Q_DECL_NOTHROW
|
||||||
{ return QBasicMutex::isRecursive(); }
|
{ return QBasicMutex::isRecursive(); }
|
||||||
|
|
||||||
@ -189,9 +229,26 @@ public:
|
|||||||
|
|
||||||
inline void lock() Q_DECL_NOTHROW {}
|
inline void lock() Q_DECL_NOTHROW {}
|
||||||
inline bool tryLock(int timeout = 0) Q_DECL_NOTHROW { Q_UNUSED(timeout); return true; }
|
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 void unlock() Q_DECL_NOTHROW {}
|
||||||
inline bool isRecursive() const Q_DECL_NOTHROW { return true; }
|
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:
|
private:
|
||||||
Q_DISABLE_COPY(QMutex)
|
Q_DISABLE_COPY(QMutex)
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user