summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qmutex.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/thread/qmutex.h')
-rw-r--r--src/corelib/thread/qmutex.h79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index a06bcd99ac..056ebdeaa5 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -44,6 +44,13 @@
#include <QtCore/qatomic.h>
#include <new>
+#if QT_HAS_INCLUDE(<chrono>)
+# include <chrono>
+# include <limits>
+#endif
+
+class tst_QMutex;
+
QT_BEGIN_NAMESPACE
@@ -60,11 +67,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 +84,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,16 +124,66 @@ 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)
+ {
+ return tryLock(convertToMilliseconds(duration));
+ }
+
+ // 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 N4606 § 30.4.1.3 [thread.timedmutex.requirements]/12.
+
+ return try_lock_for(timePoint - Clock::now());
+ }
+#endif
+
bool isRecursive() const Q_DECL_NOTHROW
{ return QBasicMutex::isRecursive(); }
private:
Q_DISABLE_COPY(QMutex)
friend class QMutexLocker;
+ friend class ::tst_QMutex;
+
+#if QT_HAS_INCLUDE(<chrono>)
+ template<class Rep, class Period>
+ static int convertToMilliseconds(std::chrono::duration<Rep, Period> duration)
+ {
+ // N4606 § 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 0;
+
+ // when converting from 'duration' to milliseconds, make sure that
+ // the result is not shorter than 'duration':
+ std::chrono::milliseconds wait = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
+ if (wait < duration)
+ wait += std::chrono::milliseconds(1);
+ Q_ASSERT(wait >= duration);
+ const auto ms = wait.count();
+ const auto maxInt = (std::numeric_limits<int>::max)();
+
+ return ms < maxInt ? int(ms) : maxInt;
+ }
+#endif
};
class Q_CORE_EXPORT QMutexLocker
@@ -189,9 +251,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)
};