1// Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QWAITCONDITION_P_H
4#define QWAITCONDITION_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists for the convenience of
11// qmutex.cpp and qmutex_unix.cpp. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <QtCore/QWaitCondition>
18#include <QtCore/QMutex>
19#include <QtCore/QDeadlineTimer>
20#include <QtCore/private/qglobal_p.h>
21
22// This header always defines a class called "mutex" and one called
23// "condition_variable", so those mustn't be used to mark ELF symbol
24// visibility. Don't add more classes to this header!
25// ELFVERSION:stop
26
27#include <condition_variable>
28#include <mutex>
29
30// There's no feature macro for C++11 std::mutex, so we use the C++14 one
31// for shared_mutex to detect it.
32// Needed for: MinGW without gthreads, Integrity
33#if __has_include(<shared_mutex>)
34# include <shared_mutex>
35#endif
36
37QT_BEGIN_NAMESPACE
38
39namespace QtPrivate {
40
41#if !defined(__cpp_lib_shared_timed_mutex)
42
43enum class cv_status { no_timeout, timeout };
44class condition_variable;
45
46class mutex : private QMutex
47{
48 friend class QtPrivate::condition_variable;
49
50public:
51 // all special member functions are ok!
52 // do not expose the (QMutex::Recursive) ctor
53 // don't use 'using QMutex::lock;' etc as those have the wrong noexcept
54
55 void lock() { return QMutex::lock(); }
56 void unlock() { return QMutex::unlock(); }
57 bool try_lock() { return QMutex::tryLock(); }
58};
59
60class condition_variable : private QWaitCondition
61{
62public:
63 // all special member functions are ok!
64
65 void notify_one() { QWaitCondition::wakeOne(); }
66 void notify_all() { QWaitCondition::wakeAll(); }
67
68 void wait(std::unique_lock<QtPrivate::mutex> &lock) { QWaitCondition::wait(lock.mutex()); }
69 template <class Predicate>
70 void wait(std::unique_lock<QtPrivate::mutex> &lock, Predicate p)
71 {
72 while (!p())
73 wait(lock);
74 }
75
76 template <typename Rep, typename Period>
77 cv_status wait_for(std::unique_lock<QtPrivate::mutex> &lock,
78 const std::chrono::duration<Rep, Period> &d)
79 {
80 return QWaitCondition::wait(lock.mutex(), QDeadlineTimer{d})
81 ? cv_status::no_timeout
82 : cv_status::timeout;
83 }
84 template <typename Rep, typename Period, typename Predicate>
85 bool wait_for(std::unique_lock<QtPrivate::mutex> &lock,
86 const std::chrono::duration<Rep, Period> &d, Predicate p)
87 {
88 const auto timer = QDeadlineTimer{d};
89 while (!p()) {
90 if (!QWaitCondition::wait(lock.mutex(), timer))
91 return p();
92 }
93 return true;
94 }
95
96 template <typename Clock, typename Duration>
97 cv_status wait_until(std::unique_lock<QtPrivate::mutex> &lock,
98 const std::chrono::time_point<Clock, Duration> &t)
99 {
100 return QWaitCondition::wait(lock.mutex(), QDeadlineTimer{t})
101 ? cv_status::no_timeout
102 : cv_status::timeout;
103 }
104
105 template <typename Clock, typename Duration, typename Predicate>
106 bool wait_until(std::unique_lock<QtPrivate::mutex> &lock,
107 const std::chrono::time_point<Clock, Duration> &t, Predicate p)
108 {
109 const auto timer = QDeadlineTimer{t};
110 while (!p()) {
111 if (!QWaitCondition::wait(lock.mutex(), timer))
112 return p();
113 }
114 return true;
115 }
116
117};
118
119#else // C++11 threads
120
121using mutex = std::mutex;
122using condition_variable = std::condition_variable;
123
124#endif // C++11 threads
125
126} // namespace QtPrivate
127
128QT_END_NAMESPACE
129
130#endif /* QWAITCONDITION_P_H */
131

source code of qtbase/src/corelib/thread/qwaitcondition_p.h