diff options
Diffstat (limited to 'src/corelib/thread/qmutex.h')
-rw-r--r-- | src/corelib/thread/qmutex.h | 79 |
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) }; |