Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwaitcondition_win.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qwaitcondition.h"
5#include "qdeadlinetimer.h"
6#include "qnamespace.h"
7#include "qmutex.h"
8#include "qreadwritelock.h"
9#include "qlist.h"
10#include "qalgorithms.h"
11
12#define Q_MUTEX_T void *
13#include <private/qmutex_p.h>
14#include <private/qreadwritelock_p.h>
15#include <qt_windows.h>
16
18
19//***********************************************************************
20// QWaitConditionPrivate
21// **********************************************************************
22
24{
25public:
27 {
28 event = CreateEvent(NULL, TRUE, FALSE, NULL);
29 }
30 inline ~QWaitConditionEvent() { CloseHandle(event); }
32 bool wokenUp;
33 HANDLE event;
34};
35
36typedef QList<QWaitConditionEvent *> EventQueue;
37
39{
40public:
44
47 void post(QWaitConditionEvent *wce, bool ret);
48};
49
51{
52 mtx.lock();
55 wce->priority = GetThreadPriority(GetCurrentThread());
56 wce->wokenUp = false;
57
58 // insert 'wce' into the queue (sorted by priority)
59 int index = 0;
60 for (; index < queue.size(); ++index) {
62 if (current->priority < wce->priority)
63 break;
64 }
65 queue.insert(index, wce);
66 mtx.unlock();
67
68 return wce;
69}
70
72{
73 // wait for the event
74 while (true) {
75 const DWORD timeout = deadline.isForever()
76 ? INFINITE
77 : DWORD(std::min(deadline.remainingTime(), qint64(INFINITE - 1)));
78
79 switch (WaitForSingleObjectEx(wce->event, timeout, FALSE)) {
80 case WAIT_OBJECT_0:
81 return true;
82 case WAIT_TIMEOUT:
83 if (deadline.hasExpired())
84 return false;
85 break;
86 default:
87 return false;
88 }
89 }
90}
91
93{
94 mtx.lock();
95
96 // remove 'wce' from the queue
97 queue.removeAll(wce);
98 ResetEvent(wce->event);
99 freeQueue.append(wce);
100
101 // wakeups delivered after the timeout should be forwarded to the next waiter
102 if (!ret && wce->wokenUp && !queue.isEmpty()) {
104 SetEvent(other->event);
105 other->wokenUp = true;
106 }
107
108 mtx.unlock();
109}
110
111//***********************************************************************
112// QWaitCondition implementation
113//***********************************************************************
114
116{
118}
119
121{
122 if (!d->queue.isEmpty()) {
123 qWarning("QWaitCondition: Destroyed while threads are still waiting");
124 qDeleteAll(d->queue);
125 }
126
127 qDeleteAll(d->freeQueue);
128 delete d;
129}
130
131bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
132{
133 if (time == std::numeric_limits<unsigned long>::max())
135 return wait(mutex, QDeadlineTimer(time));
136}
137
139{
140 if (!mutex)
141 return false;
142
143 QWaitConditionEvent *wce = d->pre();
144 mutex->unlock();
145
146 bool returnValue = d->wait(wce, deadline);
147
148 mutex->lock();
149 d->post(wce, returnValue);
150
151 return returnValue;
152}
153
154bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
155{
156 if (time == std::numeric_limits<unsigned long>::max())
157 return wait(readWriteLock, QDeadlineTimer(QDeadlineTimer::Forever));
158 return wait(readWriteLock, QDeadlineTimer(time));
159}
160
162{
163 using namespace QReadWriteLockStates;
164
165 if (!readWriteLock)
166 return false;
167 auto previousState = QReadWriteLockPrivate::stateForWaitCondition(readWriteLock);
168 if (previousState == Unlocked)
169 return false;
170 if (previousState == RecursivelyLocked) {
171 qWarning("QWaitCondition: cannot wait on QReadWriteLocks with recursive lockForWrite()");
172 return false;
173 }
174
175 QWaitConditionEvent *wce = d->pre();
176 readWriteLock->unlock();
177
178 bool returnValue = d->wait(wce, deadline);
179
180 if (previousState == LockedForWrite)
181 readWriteLock->lockForWrite();
182 else
183 readWriteLock->lockForRead();
184 d->post(wce, returnValue);
185
186 return returnValue;
187}
188
190{
191 // wake up the first waiting thread in the queue
192 QMutexLocker locker(&d->mtx);
193 for (QWaitConditionEvent *current : std::as_const(d->queue)) {
194 if (current->wokenUp)
195 continue;
196 SetEvent(current->event);
197 current->wokenUp = true;
198 break;
199 }
200}
201
203{
204 // wake up the all threads in the queue
205 QMutexLocker locker(&d->mtx);
206 for (QWaitConditionEvent *current : std::as_const(d->queue)) {
207 SetEvent(current->event);
208 current->wokenUp = true;
209 }
210}
211
\inmodule QtCore
bool hasExpired() const noexcept
Returns true if this QDeadlineTimer object has expired, false if there remains time left.
constexpr bool isForever() const noexcept
Returns true if this QDeadlineTimer object never expires, false otherwise.
qint64 remainingTime() const noexcept
Returns the remaining time in this QDeadlineTimer object in milliseconds.
static constexpr ForeverConstant Forever
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
value_type takeFirst()
Definition qlist.h:566
qsizetype removeAll(const AT &t)
Definition qlist.h:592
const T & constFirst() const noexcept
Definition qlist.h:647
void append(parameter_type t)
Definition qlist.h:458
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
Definition qmutex.h:281
void unlock() noexcept
Unlocks the mutex.
Definition qmutex.h:289
void lock() noexcept
Locks the mutex.
Definition qmutex.h:286
static QReadWriteLockStates::StateForWaitCondition stateForWaitCondition(const QReadWriteLock *lock)
\inmodule QtCore
bool wait(QDeadlineTimer deadline)
QWaitConditionEvent * pre()
void post(QWaitConditionEvent *wce, bool ret)
bool wait(QMutex *, QDeadlineTimer=QDeadlineTimer(QDeadlineTimer::Forever))
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
#define qWarning
Definition qlogging.h:166
return ret
GLuint index
[2]
GLbitfield GLuint64 timeout
[4]
struct _cl_event * event
long long qint64
Definition qtypes.h:60
QList< QWaitConditionEvent * > EventQueue
QDeadlineTimer deadline(30s)
QMutex mutex
[2]
QQueue< int > queue
[0]
QSharedPointer< T > other(t)
[5]