Line | Source Code | Coverage |
---|
1 | /**************************************************************************** | - |
2 | ** | - |
3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). | - |
4 | ** Contact: http://www.qt-project.org/legal | - |
5 | ** | - |
6 | ** This file is part of the QtCore module of the Qt Toolkit. | - |
7 | ** | - |
8 | ** $QT_BEGIN_LICENSE:LGPL$ | - |
9 | ** Commercial License Usage | - |
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - |
11 | ** accordance with the commercial license agreement provided with the | - |
12 | ** Software or, alternatively, in accordance with the terms contained in | - |
13 | ** a written agreement between you and Digia. For licensing terms and | - |
14 | ** conditions see http://qt.digia.com/licensing. For further information | - |
15 | ** use the contact form at http://qt.digia.com/contact-us. | - |
16 | ** | - |
17 | ** GNU Lesser General Public License Usage | - |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - |
19 | ** General Public License version 2.1 as published by the Free Software | - |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the | - |
21 | ** packaging of this file. Please review the following information to | - |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements | - |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | - |
24 | ** | - |
25 | ** In addition, as a special exception, Digia gives you certain additional | - |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception | - |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | - |
28 | ** | - |
29 | ** GNU General Public License Usage | - |
30 | ** Alternatively, this file may be used under the terms of the GNU | - |
31 | ** General Public License version 3.0 as published by the Free Software | - |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the | - |
33 | ** packaging of this file. Please review the following information to | - |
34 | ** ensure the GNU General Public License version 3.0 requirements will be | - |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. | - |
36 | ** | - |
37 | ** | - |
38 | ** $QT_END_LICENSE$ | - |
39 | ** | - |
40 | ****************************************************************************/ | - |
41 | | - |
42 | #include "qplatformdefs.h" | - |
43 | #include "qreadwritelock.h" | - |
44 | | - |
45 | #ifndef QT_NO_THREAD | - |
46 | #include "qmutex.h" | - |
47 | #include "qthread.h" | - |
48 | #include "qwaitcondition.h" | - |
49 | | - |
50 | #include "qreadwritelock_p.h" | - |
51 | | - |
52 | QT_BEGIN_NAMESPACE | - |
53 | | - |
54 | /*! \class QReadWriteLock | - |
55 | \inmodule QtCore | - |
56 | \brief The QReadWriteLock class provides read-write locking. | - |
57 | | - |
58 | \threadsafe | - |
59 | | - |
60 | \ingroup thread | - |
61 | | - |
62 | A read-write lock is a synchronization tool for protecting | - |
63 | resources that can be accessed for reading and writing. This type | - |
64 | of lock is useful if you want to allow multiple threads to have | - |
65 | simultaneous read-only access, but as soon as one thread wants to | - |
66 | write to the resource, all other threads must be blocked until | - |
67 | the writing is complete. | - |
68 | | - |
69 | In many cases, QReadWriteLock is a direct competitor to QMutex. | - |
70 | QReadWriteLock is a good choice if there are many concurrent | - |
71 | reads and writing occurs infrequently. | - |
72 | | - |
73 | Example: | - |
74 | | - |
75 | \snippet code/src_corelib_thread_qreadwritelock.cpp 0 | - |
76 | | - |
77 | To ensure that writers aren't blocked forever by readers, readers | - |
78 | attempting to obtain a lock will not succeed if there is a blocked | - |
79 | writer waiting for access, even if the lock is currently only | - |
80 | accessed by other readers. Also, if the lock is accessed by a | - |
81 | writer and another writer comes in, that writer will have | - |
82 | priority over any readers that might also be waiting. | - |
83 | | - |
84 | Like QMutex, a QReadWriteLock can be recursively locked by the | - |
85 | same thread when constructed with \l{QReadWriteLock::Recursive} as | - |
86 | \l{QReadWriteLock::RecursionMode}. In such cases, | - |
87 | unlock() must be called the same number of times lockForWrite() or | - |
88 | lockForRead() was called. Note that the lock type cannot be | - |
89 | changed when trying to lock recursively, i.e. it is not possible | - |
90 | to lock for reading in a thread that already has locked for | - |
91 | writing (and vice versa). | - |
92 | | - |
93 | \sa QReadLocker, QWriteLocker, QMutex, QSemaphore | - |
94 | */ | - |
95 | | - |
96 | /*! | - |
97 | \enum QReadWriteLock::RecursionMode | - |
98 | \since 4.4 | - |
99 | | - |
100 | \value Recursive In this mode, a thread can lock the same | - |
101 | QReadWriteLock multiple times and the mutex won't be unlocked | - |
102 | until a corresponding number of unlock() calls have been made. | - |
103 | | - |
104 | \value NonRecursive In this mode, a thread may only lock a | - |
105 | QReadWriteLock once. | - |
106 | | - |
107 | \sa QReadWriteLock() | - |
108 | */ | - |
109 | | - |
110 | /*! | - |
111 | \since 4.4 | - |
112 | | - |
113 | Constructs a QReadWriteLock object in the given \a recursionMode. | - |
114 | | - |
115 | The default recursion mode is NonRecursive. | - |
116 | | - |
117 | \sa lockForRead(), lockForWrite(), RecursionMode | - |
118 | */ | - |
119 | QReadWriteLock::QReadWriteLock(RecursionMode recursionMode) | - |
120 | : d(new QReadWriteLockPrivate(recursionMode)) | - |
121 | { } executed: } Execution Count:89833 | 89833 |
122 | | - |
123 | /*! | - |
124 | Destroys the QReadWriteLock object. | - |
125 | | - |
126 | \warning Destroying a read-write lock that is in use may result | - |
127 | in undefined behavior. | - |
128 | */ | - |
129 | QReadWriteLock::~QReadWriteLock() | - |
130 | { | - |
131 | delete d; executed (the execution status of this line is deduced): delete d; | - |
132 | } executed: } Execution Count:90794 | 90794 |
133 | | - |
134 | /*! | - |
135 | Locks the lock for reading. This function will block the current | - |
136 | thread if another thread has locked for writing. | - |
137 | | - |
138 | It is not possible to lock for read if the thread already has | - |
139 | locked for write. | - |
140 | | - |
141 | \sa unlock(), lockForWrite(), tryLockForRead() | - |
142 | */ | - |
143 | void QReadWriteLock::lockForRead() | - |
144 | { | - |
145 | QMutexLocker lock(&d->mutex); executed (the execution status of this line is deduced): QMutexLocker lock(&d->mutex); | - |
146 | | - |
147 | Qt::HANDLE self = 0; executed (the execution status of this line is deduced): Qt::HANDLE self = 0; | - |
148 | if (d->recursive) { evaluated: d->recursive yes Evaluation Count:3 | yes Evaluation Count:1813605 |
| 3-1813605 |
149 | self = QThread::currentThreadId(); executed (the execution status of this line is deduced): self = QThread::currentThreadId(); | - |
150 | | - |
151 | QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); executed (the execution status of this line is deduced): QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); | - |
152 | if (it != d->currentReaders.end()) { partially evaluated: it != d->currentReaders.end() no Evaluation Count:0 | yes Evaluation Count:3 |
| 0-3 |
153 | ++it.value(); never executed (the execution status of this line is deduced): ++it.value(); | - |
154 | ++d->accessCount; never executed (the execution status of this line is deduced): ++d->accessCount; | - |
155 | Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::lockForRead()", never executed (the execution status of this line is deduced): qt_noop(); | - |
156 | "Overflow in lock counter"); | - |
157 | return; | 0 |
158 | } | - |
159 | } executed: } Execution Count:3 | 3 |
160 | | - |
161 | while (d->accessCount < 0 || d->waitingWriters) { evaluated: d->accessCount < 0 yes Evaluation Count:2793 | yes Evaluation Count:1820894 |
evaluated: d->waitingWriters yes Evaluation Count:7286 | yes Evaluation Count:1813608 |
| 2793-1820894 |
162 | ++d->waitingReaders; executed (the execution status of this line is deduced): ++d->waitingReaders; | - |
163 | d->readerWait.wait(&d->mutex); executed (the execution status of this line is deduced): d->readerWait.wait(&d->mutex); | - |
164 | --d->waitingReaders; executed (the execution status of this line is deduced): --d->waitingReaders; | - |
165 | } executed: } Execution Count:10079 | 10079 |
166 | if (d->recursive) evaluated: d->recursive yes Evaluation Count:3 | yes Evaluation Count:1813605 |
| 3-1813605 |
167 | d->currentReaders.insert(self, 1); executed: d->currentReaders.insert(self, 1); Execution Count:3 | 3 |
168 | | - |
169 | ++d->accessCount; executed (the execution status of this line is deduced): ++d->accessCount; | - |
170 | Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::lockForRead()", "Overflow in lock counter"); executed (the execution status of this line is deduced): qt_noop(); | - |
171 | } executed: } Execution Count:1813608 | 1813608 |
172 | | - |
173 | /*! | - |
174 | Attempts to lock for reading. If the lock was obtained, this | - |
175 | function returns true, otherwise it returns false instead of | - |
176 | waiting for the lock to become available, i.e. it does not block. | - |
177 | | - |
178 | The lock attempt will fail if another thread has locked for | - |
179 | writing. | - |
180 | | - |
181 | If the lock was obtained, the lock must be unlocked with unlock() | - |
182 | before another thread can successfully lock it for writing. | - |
183 | | - |
184 | It is not possible to lock for read if the thread already has | - |
185 | locked for write. | - |
186 | | - |
187 | \sa unlock(), lockForRead() | - |
188 | */ | - |
189 | bool QReadWriteLock::tryLockForRead() | - |
190 | { | - |
191 | QMutexLocker lock(&d->mutex); executed (the execution status of this line is deduced): QMutexLocker lock(&d->mutex); | - |
192 | | - |
193 | Qt::HANDLE self = 0; executed (the execution status of this line is deduced): Qt::HANDLE self = 0; | - |
194 | if (d->recursive) { evaluated: d->recursive yes Evaluation Count:36 | yes Evaluation Count:7 |
| 7-36 |
195 | self = QThread::currentThreadId(); executed (the execution status of this line is deduced): self = QThread::currentThreadId(); | - |
196 | | - |
197 | QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); executed (the execution status of this line is deduced): QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); | - |
198 | if (it != d->currentReaders.end()) { evaluated: it != d->currentReaders.end() yes Evaluation Count:11 | yes Evaluation Count:25 |
| 11-25 |
199 | ++it.value(); executed (the execution status of this line is deduced): ++it.value(); | - |
200 | ++d->accessCount; executed (the execution status of this line is deduced): ++d->accessCount; | - |
201 | Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", executed (the execution status of this line is deduced): qt_noop(); | - |
202 | "Overflow in lock counter"); | - |
203 | return true; executed: return true; Execution Count:11 | 11 |
204 | } | - |
205 | } executed: } Execution Count:25 | 25 |
206 | | - |
207 | if (d->accessCount < 0) evaluated: d->accessCount < 0 yes Evaluation Count:23 | yes Evaluation Count:9 |
| 9-23 |
208 | return false; executed: return false; Execution Count:23 | 23 |
209 | if (d->recursive) evaluated: d->recursive yes Evaluation Count:4 | yes Evaluation Count:5 |
| 4-5 |
210 | d->currentReaders.insert(self, 1); executed: d->currentReaders.insert(self, 1); Execution Count:4 | 4 |
211 | | - |
212 | ++d->accessCount; executed (the execution status of this line is deduced): ++d->accessCount; | - |
213 | Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter"); executed (the execution status of this line is deduced): qt_noop(); | - |
214 | | - |
215 | return true; executed: return true; Execution Count:9 | 9 |
216 | } | - |
217 | | - |
218 | /*! \overload | - |
219 | | - |
220 | Attempts to lock for reading. This function returns true if the | - |
221 | lock was obtained; otherwise it returns false. If another thread | - |
222 | has locked for writing, this function will wait for at most \a | - |
223 | timeout milliseconds for the lock to become available. | - |
224 | | - |
225 | Note: Passing a negative number as the \a timeout is equivalent to | - |
226 | calling lockForRead(), i.e. this function will wait forever until | - |
227 | lock can be locked for reading when \a timeout is negative. | - |
228 | | - |
229 | If the lock was obtained, the lock must be unlocked with unlock() | - |
230 | before another thread can successfully lock it for writing. | - |
231 | | - |
232 | It is not possible to lock for read if the thread already has | - |
233 | locked for write. | - |
234 | | - |
235 | \sa unlock(), lockForRead() | - |
236 | */ | - |
237 | bool QReadWriteLock::tryLockForRead(int timeout) | - |
238 | { | - |
239 | QMutexLocker lock(&d->mutex); executed (the execution status of this line is deduced): QMutexLocker lock(&d->mutex); | - |
240 | | - |
241 | Qt::HANDLE self = 0; executed (the execution status of this line is deduced): Qt::HANDLE self = 0; | - |
242 | if (d->recursive) { partially evaluated: d->recursive no Evaluation Count:0 | yes Evaluation Count:3 |
| 0-3 |
243 | self = QThread::currentThreadId(); never executed (the execution status of this line is deduced): self = QThread::currentThreadId(); | - |
244 | | - |
245 | QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); never executed (the execution status of this line is deduced): QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); | - |
246 | if (it != d->currentReaders.end()) { never evaluated: it != d->currentReaders.end() | 0 |
247 | ++it.value(); never executed (the execution status of this line is deduced): ++it.value(); | - |
248 | ++d->accessCount; never executed (the execution status of this line is deduced): ++d->accessCount; | - |
249 | Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", never executed (the execution status of this line is deduced): qt_noop(); | - |
250 | "Overflow in lock counter"); | - |
251 | return true; never executed: return true; | 0 |
252 | } | - |
253 | } | 0 |
254 | | - |
255 | while (d->accessCount < 0 || d->waitingWriters) { evaluated: d->accessCount < 0 yes Evaluation Count:1 | yes Evaluation Count:2 |
partially evaluated: d->waitingWriters no Evaluation Count:0 | yes Evaluation Count:2 |
| 0-2 |
256 | ++d->waitingReaders; executed (the execution status of this line is deduced): ++d->waitingReaders; | - |
257 | bool success = d->readerWait.wait(&d->mutex, timeout < 0 ? ULONG_MAX : ulong(timeout)); executed (the execution status of this line is deduced): bool success = d->readerWait.wait(&d->mutex, timeout < 0 ? (9223372036854775807L * 2UL + 1UL) : ulong(timeout)); | - |
258 | --d->waitingReaders; executed (the execution status of this line is deduced): --d->waitingReaders; | - |
259 | if (!success) partially evaluated: !success yes Evaluation Count:1 | no Evaluation Count:0 |
| 0-1 |
260 | return false; executed: return false; Execution Count:1 | 1 |
261 | } | 0 |
262 | if (d->recursive) partially evaluated: d->recursive no Evaluation Count:0 | yes Evaluation Count:2 |
| 0-2 |
263 | d->currentReaders.insert(self, 1); never executed: d->currentReaders.insert(self, 1); | 0 |
264 | | - |
265 | ++d->accessCount; executed (the execution status of this line is deduced): ++d->accessCount; | - |
266 | Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter"); executed (the execution status of this line is deduced): qt_noop(); | - |
267 | | - |
268 | return true; executed: return true; Execution Count:2 | 2 |
269 | } | - |
270 | | - |
271 | /*! | - |
272 | Locks the lock for writing. This function will block the current | - |
273 | thread if another thread (including the current) has locked for | - |
274 | reading or writing (unless the lock has been created using the | - |
275 | \l{QReadWriteLock::Recursive} mode). | - |
276 | | - |
277 | It is not possible to lock for write if the thread already has | - |
278 | locked for read. | - |
279 | | - |
280 | \sa unlock(), lockForRead(), tryLockForWrite() | - |
281 | */ | - |
282 | void QReadWriteLock::lockForWrite() | - |
283 | { | - |
284 | QMutexLocker lock(&d->mutex); executed (the execution status of this line is deduced): QMutexLocker lock(&d->mutex); | - |
285 | | - |
286 | Qt::HANDLE self = 0; executed (the execution status of this line is deduced): Qt::HANDLE self = 0; | - |
287 | if (d->recursive) { evaluated: d->recursive yes Evaluation Count:4 | yes Evaluation Count:1169355 |
| 4-1169355 |
288 | self = QThread::currentThreadId(); executed (the execution status of this line is deduced): self = QThread::currentThreadId(); | - |
289 | | - |
290 | if (d->currentWriter == self) { partially evaluated: d->currentWriter == self no Evaluation Count:0 | yes Evaluation Count:4 |
| 0-4 |
291 | --d->accessCount; never executed (the execution status of this line is deduced): --d->accessCount; | - |
292 | Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()", never executed (the execution status of this line is deduced): qt_noop(); | - |
293 | "Overflow in lock counter"); | - |
294 | return; | 0 |
295 | } | - |
296 | } executed: } Execution Count:4 | 4 |
297 | | - |
298 | while (d->accessCount != 0) { evaluated: d->accessCount != 0 yes Evaluation Count:152141 | yes Evaluation Count:1169359 |
| 152141-1169359 |
299 | ++d->waitingWriters; executed (the execution status of this line is deduced): ++d->waitingWriters; | - |
300 | d->writerWait.wait(&d->mutex); executed (the execution status of this line is deduced): d->writerWait.wait(&d->mutex); | - |
301 | --d->waitingWriters; executed (the execution status of this line is deduced): --d->waitingWriters; | - |
302 | } executed: } Execution Count:152141 | 152141 |
303 | if (d->recursive) evaluated: d->recursive yes Evaluation Count:4 | yes Evaluation Count:1169355 |
| 4-1169355 |
304 | d->currentWriter = self; executed: d->currentWriter = self; Execution Count:4 | 4 |
305 | | - |
306 | --d->accessCount; executed (the execution status of this line is deduced): --d->accessCount; | - |
307 | Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()", "Overflow in lock counter"); executed (the execution status of this line is deduced): qt_noop(); | - |
308 | } executed: } Execution Count:1169359 | 1169359 |
309 | | - |
310 | /*! | - |
311 | Attempts to lock for writing. If the lock was obtained, this | - |
312 | function returns true; otherwise, it returns false immediately. | - |
313 | | - |
314 | The lock attempt will fail if another thread has locked for | - |
315 | reading or writing. | - |
316 | | - |
317 | If the lock was obtained, the lock must be unlocked with unlock() | - |
318 | before another thread can successfully lock it. | - |
319 | | - |
320 | It is not possible to lock for write if the thread already has | - |
321 | locked for read. | - |
322 | | - |
323 | \sa unlock(), lockForWrite() | - |
324 | */ | - |
325 | bool QReadWriteLock::tryLockForWrite() | - |
326 | { | - |
327 | QMutexLocker lock(&d->mutex); executed (the execution status of this line is deduced): QMutexLocker lock(&d->mutex); | - |
328 | | - |
329 | Qt::HANDLE self = 0; executed (the execution status of this line is deduced): Qt::HANDLE self = 0; | - |
330 | if (d->recursive) { evaluated: d->recursive yes Evaluation Count:39 | yes Evaluation Count:23 |
| 23-39 |
331 | self = QThread::currentThreadId(); executed (the execution status of this line is deduced): self = QThread::currentThreadId(); | - |
332 | | - |
333 | if (d->currentWriter == self) { evaluated: d->currentWriter == self yes Evaluation Count:12 | yes Evaluation Count:27 |
| 12-27 |
334 | --d->accessCount; executed (the execution status of this line is deduced): --d->accessCount; | - |
335 | Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()", executed (the execution status of this line is deduced): qt_noop(); | - |
336 | "Overflow in lock counter"); | - |
337 | return true; executed: return true; Execution Count:12 | 12 |
338 | } | - |
339 | } executed: } Execution Count:27 | 27 |
340 | | - |
341 | if (d->accessCount != 0) evaluated: d->accessCount != 0 yes Evaluation Count:32 | yes Evaluation Count:18 |
| 18-32 |
342 | return false; executed: return false; Execution Count:32 | 32 |
343 | if (d->recursive) evaluated: d->recursive yes Evaluation Count:5 | yes Evaluation Count:13 |
| 5-13 |
344 | d->currentWriter = self; executed: d->currentWriter = self; Execution Count:5 | 5 |
345 | | - |
346 | --d->accessCount; executed (the execution status of this line is deduced): --d->accessCount; | - |
347 | Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::tryLockForWrite()", executed (the execution status of this line is deduced): qt_noop(); | - |
348 | "Overflow in lock counter"); | - |
349 | | - |
350 | return true; executed: return true; Execution Count:18 | 18 |
351 | } | - |
352 | | - |
353 | /*! \overload | - |
354 | | - |
355 | Attempts to lock for writing. This function returns true if the | - |
356 | lock was obtained; otherwise it returns false. If another thread | - |
357 | has locked for reading or writing, this function will wait for at | - |
358 | most \a timeout milliseconds for the lock to become available. | - |
359 | | - |
360 | Note: Passing a negative number as the \a timeout is equivalent to | - |
361 | calling lockForWrite(), i.e. this function will wait forever until | - |
362 | lock can be locked for writing when \a timeout is negative. | - |
363 | | - |
364 | If the lock was obtained, the lock must be unlocked with unlock() | - |
365 | before another thread can successfully lock it. | - |
366 | | - |
367 | It is not possible to lock for write if the thread already has | - |
368 | locked for read. | - |
369 | | - |
370 | \sa unlock(), lockForWrite() | - |
371 | */ | - |
372 | bool QReadWriteLock::tryLockForWrite(int timeout) | - |
373 | { | - |
374 | QMutexLocker lock(&d->mutex); executed (the execution status of this line is deduced): QMutexLocker lock(&d->mutex); | - |
375 | | - |
376 | Qt::HANDLE self = 0; executed (the execution status of this line is deduced): Qt::HANDLE self = 0; | - |
377 | if (d->recursive) { partially evaluated: d->recursive no Evaluation Count:0 | yes Evaluation Count:2 |
| 0-2 |
378 | self = QThread::currentThreadId(); never executed (the execution status of this line is deduced): self = QThread::currentThreadId(); | - |
379 | | - |
380 | if (d->currentWriter == self) { never evaluated: d->currentWriter == self | 0 |
381 | --d->accessCount; never executed (the execution status of this line is deduced): --d->accessCount; | - |
382 | Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::lockForWrite()", never executed (the execution status of this line is deduced): qt_noop(); | - |
383 | "Overflow in lock counter"); | - |
384 | return true; never executed: return true; | 0 |
385 | } | - |
386 | } | 0 |
387 | | - |
388 | while (d->accessCount != 0) { evaluated: d->accessCount != 0 yes Evaluation Count:1 | yes Evaluation Count:1 |
| 1 |
389 | ++d->waitingWriters; executed (the execution status of this line is deduced): ++d->waitingWriters; | - |
390 | bool success = d->writerWait.wait(&d->mutex, timeout < 0 ? ULONG_MAX : ulong(timeout)); executed (the execution status of this line is deduced): bool success = d->writerWait.wait(&d->mutex, timeout < 0 ? (9223372036854775807L * 2UL + 1UL) : ulong(timeout)); | - |
391 | --d->waitingWriters; executed (the execution status of this line is deduced): --d->waitingWriters; | - |
392 | | - |
393 | if (!success) partially evaluated: !success yes Evaluation Count:1 | no Evaluation Count:0 |
| 0-1 |
394 | return false; executed: return false; Execution Count:1 | 1 |
395 | } | 0 |
396 | if (d->recursive) partially evaluated: d->recursive no Evaluation Count:0 | yes Evaluation Count:1 |
| 0-1 |
397 | d->currentWriter = self; never executed: d->currentWriter = self; | 0 |
398 | | - |
399 | --d->accessCount; executed (the execution status of this line is deduced): --d->accessCount; | - |
400 | Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::tryLockForWrite()", executed (the execution status of this line is deduced): qt_noop(); | - |
401 | "Overflow in lock counter"); | - |
402 | | - |
403 | return true; executed: return true; Execution Count:1 | 1 |
404 | } | - |
405 | | - |
406 | /*! | - |
407 | Unlocks the lock. | - |
408 | | - |
409 | Attempting to unlock a lock that is not locked is an error, and will result | - |
410 | in program termination. | - |
411 | | - |
412 | \sa lockForRead(), lockForWrite(), tryLockForRead(), tryLockForWrite() | - |
413 | */ | - |
414 | void QReadWriteLock::unlock() | - |
415 | { | - |
416 | QMutexLocker lock(&d->mutex); executed (the execution status of this line is deduced): QMutexLocker lock(&d->mutex); | - |
417 | | - |
418 | Q_ASSERT_X(d->accessCount != 0, "QReadWriteLock::unlock()", "Cannot unlock an unlocked lock"); executed (the execution status of this line is deduced): qt_noop(); | - |
419 | | - |
420 | bool unlocked = false; executed (the execution status of this line is deduced): bool unlocked = false; | - |
421 | if (d->accessCount > 0) { evaluated: d->accessCount > 0 yes Evaluation Count:1813630 | yes Evaluation Count:1169390 |
| 1169390-1813630 |
422 | // releasing a read lock | - |
423 | if (d->recursive) { evaluated: d->recursive yes Evaluation Count:18 | yes Evaluation Count:1813612 |
| 18-1813612 |
424 | Qt::HANDLE self = QThread::currentThreadId(); executed (the execution status of this line is deduced): Qt::HANDLE self = QThread::currentThreadId(); | - |
425 | QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); executed (the execution status of this line is deduced): QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); | - |
426 | if (it != d->currentReaders.end()) { partially evaluated: it != d->currentReaders.end() yes Evaluation Count:18 | no Evaluation Count:0 |
| 0-18 |
427 | if (--it.value() <= 0) evaluated: --it.value() <= 0 yes Evaluation Count:7 | yes Evaluation Count:11 |
| 7-11 |
428 | d->currentReaders.erase(it); executed: d->currentReaders.erase(it); Execution Count:7 | 7 |
429 | } executed: } Execution Count:18 | 18 |
430 | } executed: } Execution Count:18 | 18 |
431 | | - |
432 | unlocked = --d->accessCount == 0; executed (the execution status of this line is deduced): unlocked = --d->accessCount == 0; | - |
433 | } else if (d->accessCount < 0 && ++d->accessCount == 0) { executed: } Execution Count:1813630 partially evaluated: d->accessCount < 0 yes Evaluation Count:1169390 | no Evaluation Count:0 |
evaluated: ++d->accessCount == 0 yes Evaluation Count:1169378 | yes Evaluation Count:12 |
| 0-1813630 |
434 | // released a write lock | - |
435 | unlocked = true; executed (the execution status of this line is deduced): unlocked = true; | - |
436 | d->currentWriter = 0; executed (the execution status of this line is deduced): d->currentWriter = 0; | - |
437 | } executed: } Execution Count:1169378 | 1169378 |
438 | | - |
439 | if (unlocked) { evaluated: unlocked yes Evaluation Count:2805032 | yes Evaluation Count:177987 |
| 177987-2805032 |
440 | if (d->waitingWriters) { evaluated: d->waitingWriters yes Evaluation Count:152442 | yes Evaluation Count:2652591 |
| 152442-2652591 |
441 | d->writerWait.wakeOne(); executed (the execution status of this line is deduced): d->writerWait.wakeOne(); | - |
442 | } else if (d->waitingReaders) { executed: } Execution Count:152442 evaluated: d->waitingReaders yes Evaluation Count:32113 | yes Evaluation Count:2620478 |
| 32113-2620478 |
443 | d->readerWait.wakeAll(); executed (the execution status of this line is deduced): d->readerWait.wakeAll(); | - |
444 | } executed: } Execution Count:32113 | 32113 |
445 | } | - |
446 | } executed: } Execution Count:2983020 | 2983020 |
447 | | - |
448 | /*! | - |
449 | \class QReadLocker | - |
450 | \inmodule QtCore | - |
451 | \brief The QReadLocker class is a convenience class that | - |
452 | simplifies locking and unlocking read-write locks for read access. | - |
453 | | - |
454 | \threadsafe | - |
455 | | - |
456 | \ingroup thread | - |
457 | | - |
458 | The purpose of QReadLocker (and QWriteLocker) is to simplify | - |
459 | QReadWriteLock locking and unlocking. Locking and unlocking | - |
460 | statements or in exception handling code is error-prone and | - |
461 | difficult to debug. QReadLocker can be used in such situations | - |
462 | to ensure that the state of the lock is always well-defined. | - |
463 | | - |
464 | Here's an example that uses QReadLocker to lock and unlock a | - |
465 | read-write lock for reading: | - |
466 | | - |
467 | \snippet code/src_corelib_thread_qreadwritelock.cpp 1 | - |
468 | | - |
469 | It is equivalent to the following code: | - |
470 | | - |
471 | \snippet code/src_corelib_thread_qreadwritelock.cpp 2 | - |
472 | | - |
473 | The QMutexLocker documentation shows examples where the use of a | - |
474 | locker object greatly simplifies programming. | - |
475 | | - |
476 | \sa QWriteLocker, QReadWriteLock | - |
477 | */ | - |
478 | | - |
479 | /*! | - |
480 | \fn QReadLocker::QReadLocker(QReadWriteLock *lock) | - |
481 | | - |
482 | Constructs a QReadLocker and locks \a lock for reading. The lock | - |
483 | will be unlocked when the QReadLocker is destroyed. If \c lock is | - |
484 | zero, QReadLocker does nothing. | - |
485 | | - |
486 | \sa QReadWriteLock::lockForRead() | - |
487 | */ | - |
488 | | - |
489 | /*! | - |
490 | \fn QReadLocker::~QReadLocker() | - |
491 | | - |
492 | Destroys the QReadLocker and unlocks the lock that was passed to | - |
493 | the constructor. | - |
494 | | - |
495 | \sa QReadWriteLock::unlock() | - |
496 | */ | - |
497 | | - |
498 | /*! | - |
499 | \fn void QReadLocker::unlock() | - |
500 | | - |
501 | Unlocks the lock associated with this locker. | - |
502 | | - |
503 | \sa QReadWriteLock::unlock() | - |
504 | */ | - |
505 | | - |
506 | /*! | - |
507 | \fn void QReadLocker::relock() | - |
508 | | - |
509 | Relocks an unlocked lock. | - |
510 | | - |
511 | \sa unlock() | - |
512 | */ | - |
513 | | - |
514 | /*! | - |
515 | \fn QReadWriteLock *QReadLocker::readWriteLock() const | - |
516 | | - |
517 | Returns a pointer to the read-write lock that was passed | - |
518 | to the constructor. | - |
519 | */ | - |
520 | | - |
521 | /*! | - |
522 | \class QWriteLocker | - |
523 | \inmodule QtCore | - |
524 | \brief The QWriteLocker class is a convenience class that | - |
525 | simplifies locking and unlocking read-write locks for write access. | - |
526 | | - |
527 | \threadsafe | - |
528 | | - |
529 | \ingroup thread | - |
530 | | - |
531 | The purpose of QWriteLocker (and QReadLocker) is to simplify | - |
532 | QReadWriteLock locking and unlocking. Locking and unlocking | - |
533 | statements or in exception handling code is error-prone and | - |
534 | difficult to debug. QWriteLocker can be used in such situations | - |
535 | to ensure that the state of the lock is always well-defined. | - |
536 | | - |
537 | Here's an example that uses QWriteLocker to lock and unlock a | - |
538 | read-write lock for writing: | - |
539 | | - |
540 | \snippet code/src_corelib_thread_qreadwritelock.cpp 3 | - |
541 | | - |
542 | It is equivalent to the following code: | - |
543 | | - |
544 | \snippet code/src_corelib_thread_qreadwritelock.cpp 4 | - |
545 | | - |
546 | The QMutexLocker documentation shows examples where the use of a | - |
547 | locker object greatly simplifies programming. | - |
548 | | - |
549 | \sa QReadLocker, QReadWriteLock | - |
550 | */ | - |
551 | | - |
552 | /*! | - |
553 | \fn QWriteLocker::QWriteLocker(QReadWriteLock *lock) | - |
554 | | - |
555 | Constructs a QWriteLocker and locks \a lock for writing. The lock | - |
556 | will be unlocked when the QWriteLocker is destroyed. If \c lock is | - |
557 | zero, QWriteLocker does nothing. | - |
558 | | - |
559 | \sa QReadWriteLock::lockForWrite() | - |
560 | */ | - |
561 | | - |
562 | /*! | - |
563 | \fn QWriteLocker::~QWriteLocker() | - |
564 | | - |
565 | Destroys the QWriteLocker and unlocks the lock that was passed to | - |
566 | the constructor. | - |
567 | | - |
568 | \sa QReadWriteLock::unlock() | - |
569 | */ | - |
570 | | - |
571 | /*! | - |
572 | \fn void QWriteLocker::unlock() | - |
573 | | - |
574 | Unlocks the lock associated with this locker. | - |
575 | | - |
576 | \sa QReadWriteLock::unlock() | - |
577 | */ | - |
578 | | - |
579 | /*! | - |
580 | \fn void QWriteLocker::relock() | - |
581 | | - |
582 | Relocks an unlocked lock. | - |
583 | | - |
584 | \sa unlock() | - |
585 | */ | - |
586 | | - |
587 | /*! | - |
588 | \fn QReadWriteLock *QWriteLocker::readWriteLock() const | - |
589 | | - |
590 | Returns a pointer to the read-write lock that was passed | - |
591 | to the constructor. | - |
592 | */ | - |
593 | | - |
594 | QT_END_NAMESPACE | - |
595 | | - |
596 | #endif // QT_NO_THREAD | - |
597 | | - |
| | |