| 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 | | - |
| | |