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);
|
||||
}
|
||||
|
||||
/*! \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
|
||||
|
@ -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)
|
||||
{
|
||||
// § 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
|
||||
{ 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)
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user