| Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/corelib/thread/qreadwritelock.cpp |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /**************************************************************************** | - | ||||||||||||||||||||||||
| 2 | ** | - | ||||||||||||||||||||||||
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | - | ||||||||||||||||||||||||
| 4 | ** Copyright (C) 2016 Intel Corporation. | - | ||||||||||||||||||||||||
| 5 | ** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com> | - | ||||||||||||||||||||||||
| 6 | ** Contact: https://www.qt.io/licensing/ | - | ||||||||||||||||||||||||
| 7 | ** | - | ||||||||||||||||||||||||
| 8 | ** This file is part of the QtCore module of the Qt Toolkit. | - | ||||||||||||||||||||||||
| 9 | ** | - | ||||||||||||||||||||||||
| 10 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||||||||||||||||||||
| 11 | ** Commercial License Usage | - | ||||||||||||||||||||||||
| 12 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||||||||||||||
| 13 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||||||||||||||
| 14 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||||||||||||||
| 15 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||||||||||||||
| 16 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||||||||||||||||||||
| 17 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||||||||||||||||||||
| 18 | ** | - | ||||||||||||||||||||||||
| 19 | ** GNU Lesser General Public License Usage | - | ||||||||||||||||||||||||
| 20 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||||||||||||||
| 21 | ** General Public License version 3 as published by the Free Software | - | ||||||||||||||||||||||||
| 22 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||||||||||||||||||||
| 23 | ** packaging of this file. Please review the following information to | - | ||||||||||||||||||||||||
| 24 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||||||||||||||||||||
| 25 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||||||||||||||||||||
| 26 | ** | - | ||||||||||||||||||||||||
| 27 | ** GNU General Public License Usage | - | ||||||||||||||||||||||||
| 28 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||||||||||||||||||||
| 29 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||||||||||||||||||||
| 30 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||||||||||||||||||||
| 31 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||||||||||||||||||||
| 32 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||||||||||||||||||||
| 33 | ** included in the packaging of this file. Please review the following | - | ||||||||||||||||||||||||
| 34 | ** information to ensure the GNU General Public License requirements will | - | ||||||||||||||||||||||||
| 35 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||||||||||||||||||||
| 36 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||||||||||||||||||||
| 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 | #include "qreadwritelock_p.h" | - | ||||||||||||||||||||||||
| 50 | #include "qelapsedtimer.h" | - | ||||||||||||||||||||||||
| 51 | #include "private/qfreelist_p.h" | - | ||||||||||||||||||||||||
| 52 | - | |||||||||||||||||||||||||
| 53 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||||||||
| 54 | - | |||||||||||||||||||||||||
| 55 | /* | - | ||||||||||||||||||||||||
| 56 | * Implementation details of QReadWriteLock: | - | ||||||||||||||||||||||||
| 57 | * | - | ||||||||||||||||||||||||
| 58 | * Depending on the valued of d_ptr, the lock is in the following state: | - | ||||||||||||||||||||||||
| 59 | * - when d_ptr == 0x0: Unlocked (no readers, no writers) and non-recursive. | - | ||||||||||||||||||||||||
| 60 | * - when d_ptr & 0x1: If the least significant bit is set, we are locked for read. | - | ||||||||||||||||||||||||
| 61 | * In that case, d_ptr>>4 represents the number of reading threads minus 1. No writers | - | ||||||||||||||||||||||||
| 62 | * are waiting, and the lock is not recursive. | - | ||||||||||||||||||||||||
| 63 | * - when d_ptr == 0x2: We are locked for write and nobody is waiting. (no contention) | - | ||||||||||||||||||||||||
| 64 | * - In any other case, d_ptr points to an actual QReadWriteLockPrivate. | - | ||||||||||||||||||||||||
| 65 | */ | - | ||||||||||||||||||||||||
| 66 | - | |||||||||||||||||||||||||
| 67 | namespace { | - | ||||||||||||||||||||||||
| 68 | enum { | - | ||||||||||||||||||||||||
| 69 | StateMask = 0x3, | - | ||||||||||||||||||||||||
| 70 | StateLockedForRead = 0x1, | - | ||||||||||||||||||||||||
| 71 | StateLockedForWrite = 0x2, | - | ||||||||||||||||||||||||
| 72 | }; | - | ||||||||||||||||||||||||
| 73 | const auto dummyLockedForRead = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(StateLockedForRead)); | - | ||||||||||||||||||||||||
| 74 | const auto dummyLockedForWrite = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(StateLockedForWrite)); | - | ||||||||||||||||||||||||
| 75 | inline bool isUncontendedLocked(const QReadWriteLockPrivate *d) | - | ||||||||||||||||||||||||
| 76 | { executed 317361 times by 523 tests: return quintptr(d) & StateMask;Executed by:
executed 317361 times by 523 tests: return quintptr(d) & StateMask; }return quintptr(d) & StateMask;Executed by:
executed 317361 times by 523 tests: return quintptr(d) & StateMask;Executed by:
| 317361 | ||||||||||||||||||||||||
| 77 | } | - | ||||||||||||||||||||||||
| 78 | - | |||||||||||||||||||||||||
| 79 | /*! \class QReadWriteLock | - | ||||||||||||||||||||||||
| 80 | \inmodule QtCore | - | ||||||||||||||||||||||||
| 81 | \brief The QReadWriteLock class provides read-write locking. | - | ||||||||||||||||||||||||
| 82 | - | |||||||||||||||||||||||||
| 83 | \threadsafe | - | ||||||||||||||||||||||||
| 84 | - | |||||||||||||||||||||||||
| 85 | \ingroup thread | - | ||||||||||||||||||||||||
| 86 | - | |||||||||||||||||||||||||
| 87 | A read-write lock is a synchronization tool for protecting | - | ||||||||||||||||||||||||
| 88 | resources that can be accessed for reading and writing. This type | - | ||||||||||||||||||||||||
| 89 | of lock is useful if you want to allow multiple threads to have | - | ||||||||||||||||||||||||
| 90 | simultaneous read-only access, but as soon as one thread wants to | - | ||||||||||||||||||||||||
| 91 | write to the resource, all other threads must be blocked until | - | ||||||||||||||||||||||||
| 92 | the writing is complete. | - | ||||||||||||||||||||||||
| 93 | - | |||||||||||||||||||||||||
| 94 | In many cases, QReadWriteLock is a direct competitor to QMutex. | - | ||||||||||||||||||||||||
| 95 | QReadWriteLock is a good choice if there are many concurrent | - | ||||||||||||||||||||||||
| 96 | reads and writing occurs infrequently. | - | ||||||||||||||||||||||||
| 97 | - | |||||||||||||||||||||||||
| 98 | Example: | - | ||||||||||||||||||||||||
| 99 | - | |||||||||||||||||||||||||
| 100 | \snippet code/src_corelib_thread_qreadwritelock.cpp 0 | - | ||||||||||||||||||||||||
| 101 | - | |||||||||||||||||||||||||
| 102 | To ensure that writers aren't blocked forever by readers, readers | - | ||||||||||||||||||||||||
| 103 | attempting to obtain a lock will not succeed if there is a blocked | - | ||||||||||||||||||||||||
| 104 | writer waiting for access, even if the lock is currently only | - | ||||||||||||||||||||||||
| 105 | accessed by other readers. Also, if the lock is accessed by a | - | ||||||||||||||||||||||||
| 106 | writer and another writer comes in, that writer will have | - | ||||||||||||||||||||||||
| 107 | priority over any readers that might also be waiting. | - | ||||||||||||||||||||||||
| 108 | - | |||||||||||||||||||||||||
| 109 | Like QMutex, a QReadWriteLock can be recursively locked by the | - | ||||||||||||||||||||||||
| 110 | same thread when constructed with \l{QReadWriteLock::Recursive} as | - | ||||||||||||||||||||||||
| 111 | \l{QReadWriteLock::RecursionMode}. In such cases, | - | ||||||||||||||||||||||||
| 112 | unlock() must be called the same number of times lockForWrite() or | - | ||||||||||||||||||||||||
| 113 | lockForRead() was called. Note that the lock type cannot be | - | ||||||||||||||||||||||||
| 114 | changed when trying to lock recursively, i.e. it is not possible | - | ||||||||||||||||||||||||
| 115 | to lock for reading in a thread that already has locked for | - | ||||||||||||||||||||||||
| 116 | writing (and vice versa). | - | ||||||||||||||||||||||||
| 117 | - | |||||||||||||||||||||||||
| 118 | \sa QReadLocker, QWriteLocker, QMutex, QSemaphore | - | ||||||||||||||||||||||||
| 119 | */ | - | ||||||||||||||||||||||||
| 120 | - | |||||||||||||||||||||||||
| 121 | /*! | - | ||||||||||||||||||||||||
| 122 | \enum QReadWriteLock::RecursionMode | - | ||||||||||||||||||||||||
| 123 | \since 4.4 | - | ||||||||||||||||||||||||
| 124 | - | |||||||||||||||||||||||||
| 125 | \value Recursive In this mode, a thread can lock the same | - | ||||||||||||||||||||||||
| 126 | QReadWriteLock multiple times. The QReadWriteLock won't be unlocked | - | ||||||||||||||||||||||||
| 127 | until a corresponding number of unlock() calls have been made. | - | ||||||||||||||||||||||||
| 128 | - | |||||||||||||||||||||||||
| 129 | \value NonRecursive In this mode, a thread may only lock a | - | ||||||||||||||||||||||||
| 130 | QReadWriteLock once. | - | ||||||||||||||||||||||||
| 131 | - | |||||||||||||||||||||||||
| 132 | \sa QReadWriteLock() | - | ||||||||||||||||||||||||
| 133 | */ | - | ||||||||||||||||||||||||
| 134 | - | |||||||||||||||||||||||||
| 135 | /*! | - | ||||||||||||||||||||||||
| 136 | \since 4.4 | - | ||||||||||||||||||||||||
| 137 | - | |||||||||||||||||||||||||
| 138 | Constructs a QReadWriteLock object in the given \a recursionMode. | - | ||||||||||||||||||||||||
| 139 | - | |||||||||||||||||||||||||
| 140 | The default recursion mode is NonRecursive. | - | ||||||||||||||||||||||||
| 141 | - | |||||||||||||||||||||||||
| 142 | \sa lockForRead(), lockForWrite(), RecursionMode | - | ||||||||||||||||||||||||
| 143 | */ | - | ||||||||||||||||||||||||
| 144 | QReadWriteLock::QReadWriteLock(RecursionMode recursionMode) | - | ||||||||||||||||||||||||
| 145 | : dd_ptr(recursionMode == Recursive ? new QReadWriteLockPrivate(recursionMode))true) : nullptr) | - | ||||||||||||||||||||||||
| 146 | { | - | ||||||||||||||||||||||||
| 147 | Q_ASSERT_X(!(quintptr(d_ptr.load()) & StateMask), "QReadWriteLock::QReadWriteLock", "bad d_ptr alignment"); | - | ||||||||||||||||||||||||
| 148 | } executed 42232 times by 296 tests: end of blockExecuted by:
| 42232 | ||||||||||||||||||||||||
| 149 | - | |||||||||||||||||||||||||
| 150 | /*! | - | ||||||||||||||||||||||||
| 151 | Destroys the QReadWriteLock object. | - | ||||||||||||||||||||||||
| 152 | - | |||||||||||||||||||||||||
| 153 | \warning Destroying a read-write lock that is in use may result | - | ||||||||||||||||||||||||
| 154 | in undefined behavior. | - | ||||||||||||||||||||||||
| 155 | */ | - | ||||||||||||||||||||||||
| 156 | QReadWriteLock::~QReadWriteLock() | - | ||||||||||||||||||||||||
| 157 | { | - | ||||||||||||||||||||||||
| 158 | auto d = d_ptr.load(); | - | ||||||||||||||||||||||||
| 159 | if (isUncontendedLocked(d))
| 0-43112 | ||||||||||||||||||||||||
| 160 | qWarning("QReadWriteLock: destroying locked QReadWriteLock"); | - | ||||||||||||||||||||||||
| 161 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 162 | } | - | ||||||||||||||||||||||||
| 163 | delete d; | - | ||||||||||||||||||||||||
| 164 | } executed 43112 times by 519 tests: end of blockExecuted by:
| 43112 | ||||||||||||||||||||||||
| 165 | - | |||||||||||||||||||||||||
| 166 | /*! | - | ||||||||||||||||||||||||
| 167 | Locks the lock for reading. This function will block the current | - | ||||||||||||||||||||||||
| 168 | thread if another thread has locked for writing. | - | ||||||||||||||||||||||||
| 169 | - | |||||||||||||||||||||||||
| 170 | It is not possible to lock for read if the thread already has | - | ||||||||||||||||||||||||
| 171 | locked for write. | - | ||||||||||||||||||||||||
| 172 | - | |||||||||||||||||||||||||
| 173 | \sa unlock(), lockForWrite(), tryLockForRead() | - | ||||||||||||||||||||||||
| 174 | */ | - | ||||||||||||||||||||||||
| 175 | void QReadWriteLock::lockForRead() | - | ||||||||||||||||||||||||
| 176 | { | - | ||||||||||||||||||||||||
| 177 | QMutexLocker lockif (&d->mutexd_ptr.testAndSetAcquire(nullptr, dummyLockedForRead))
| 143670-1557572 | ||||||||||||||||||||||||
| 178 | return; executed 1557572 times by 355 tests: return;Executed by:
| 1557572 | ||||||||||||||||||||||||
| 179 | tryLockForRead(-1); | - | ||||||||||||||||||||||||
| Qt executed 143670 times by 10 tests: }end of blockExecuted by:
executed 143670 times by 10 tests: end of blockExecuted by:
| ||||||||||||||||||||||||||
| 181 | - | |||||||||||||||||||||||||
| 182 | /*! | - | ||||||||||||||||||||||||
| 183 | Attempts to lock for reading. If the lock was obtained, this | - | ||||||||||||||||||||||||
| 184 | function returns \c true, otherwise it returns \c false instead of | - | ||||||||||||||||||||||||
| 185 | waiting for the lock to become available, i.e. it does not block. | - | ||||||||||||||||||||||||
| 186 | - | |||||||||||||||||||||||||
| 187 | The lock attempt will fail if another thread has locked for | - | ||||||||||||||||||||||||
| 188 | writing. | - | ||||||||||||||||||||||||
| 189 | - | |||||||||||||||||||||||||
| 190 | If the lock was obtained, the lock must be unlocked with unlock() | - | ||||||||||||||||||||||||
| 191 | before another thread can successfully lock it for writing. | - | ||||||||||||||||||||||||
| 192 | - | |||||||||||||||||||||||||
| 193 | It is not possible to lock for read if the thread already has | - | ||||||||||||||||||||||||
| 194 | locked for write. | - | ||||||||||||||||||||||||
| 195 | - | |||||||||||||||||||||||||
| 196 | \sa unlock(), lockForRead() | - | ||||||||||||||||||||||||
| 197 | */ | - | ||||||||||||||||||||||||
| 198 | bool QReadWriteLock::HANDLE self =tryLockForRead() | - | ||||||||||||||||||||||||
| 199 | { | - | ||||||||||||||||||||||||
| 200 | return tryLockForRead( executed 43 times by 2 tests: 0);return tryLockForRead(0);Executed by:
executed 43 times by 2 tests: return tryLockForRead(0);Executed by:
| 43 | ||||||||||||||||||||||||
| 201 | } | - | ||||||||||||||||||||||||
| 202 | - | |||||||||||||||||||||||||
| 203 | /*! \overload | - | ||||||||||||||||||||||||
| 204 | - | |||||||||||||||||||||||||
| 205 | Attempts to lock for reading. This function returns \c true if the | - | ||||||||||||||||||||||||
| 206 | lock was obtained; otherwise it returns \c false. If another thread | - | ||||||||||||||||||||||||
| 207 | has locked for writing, this function will wait for at most \a | - | ||||||||||||||||||||||||
| 208 | timeout milliseconds for the lock to become available. | - | ||||||||||||||||||||||||
| 209 | - | |||||||||||||||||||||||||
| 210 | Note: Passing a negative number as the \a timeout is equivalent to | - | ||||||||||||||||||||||||
| 211 | calling lockForRead(), i.e. this function will wait forever until | - | ||||||||||||||||||||||||
| 212 | lock can be locked for reading when \a timeout is negative. | - | ||||||||||||||||||||||||
| 213 | - | |||||||||||||||||||||||||
| 214 | If the lock was obtained, the lock must be unlocked with unlock() | - | ||||||||||||||||||||||||
| 215 | before another thread can successfully lock it for writing. | - | ||||||||||||||||||||||||
| 216 | - | |||||||||||||||||||||||||
| 217 | It is not possible to lock for read if the thread already has | - | ||||||||||||||||||||||||
| 218 | locked for write. | - | ||||||||||||||||||||||||
| 219 | - | |||||||||||||||||||||||||
| 220 | \sa unlock(), lockForRead() | - | ||||||||||||||||||||||||
| 221 | */ | - | ||||||||||||||||||||||||
| 222 | bool QReadWriteLock::tryLockForRead(int timeout) | - | ||||||||||||||||||||||||
| 223 | { | - | ||||||||||||||||||||||||
| 224 | // Fast case: non contended: | - | ||||||||||||||||||||||||
| 225 | QReadWriteLockPrivate *d; | - | ||||||||||||||||||||||||
| 226 | if (d_ptr.testAndSetAcquire(nullptr, dummyLockedForRead, d->recursive))
| 4-143712 | ||||||||||||||||||||||||
| 227 | return true; executed 4 times by 1 test: return true;Executed by:
| 4 | ||||||||||||||||||||||||
| 228 | - | |||||||||||||||||||||||||
| 229 | while (true) { | - | ||||||||||||||||||||||||
| 230 | self = QThread::currentThreadId();
| 0-143712 | ||||||||||||||||||||||||
QHash<Qt::HANDLE, int>::iterator it =
| ||||||||||||||||||||||||||
| 231 | if (!d_ptr
| 0 | ||||||||||||||||||||||||
| 232 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 233 | return true; never executed: return true; | 0 | ||||||||||||||||||||||||
| 234 | } | - | ||||||||||||||||||||||||
| 235 | - | |||||||||||||||||||||||||
| 236 | if ((quintptr(it !=d->currentReaders.end())) & StateMask) == StateLockedForRead) {
| 11198-132514 | ||||||||||||||||||||||||
| 237 | ++it.value(); | - | ||||||||||||||||||||||||
| ++// locked for read, increase the counter | ||||||||||||||||||||||||||
| 238 | const auto val = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(d->accessCount;) + (1U<<4)); | - | ||||||||||||||||||||||||
| 239 | Q_ASSERT_X(d->accessCountquintptr(val) > 0,(1U<<4), "QReadWriteLock::lockForReadtryLockForRead()", | - | ||||||||||||||||||||||||
| 240 | "Overflow in lock counter"); | - | ||||||||||||||||||||||||
| 241 | if (!d_ptr.testAndSetAcquire(d, val, d))
| 0-11198 | ||||||||||||||||||||||||
| 242 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 243 | return true; executed 11198 times by 6 tests: return true;Executed by:
| 11198 | ||||||||||||||||||||||||
| 244 | }} | - | ||||||||||||||||||||||||
| 245 | - | |||||||||||||||||||||||||
| 246 | whileif (d->accessCount < 0 ||d ->waitingWriters== dummyLockedForWrite) {
| 42-132472 | ||||||||||||||||||||||||
| 247 | ++d->waitingReadersif (!timeout)
| 2-40 | ||||||||||||||||||||||||
| 248 | return false executed 2 times by 1 test: ;return false;Executed by:
executed 2 times by 1 test: return false;Executed by:
| 2 | ||||||||||||||||||||||||
| 249 | - | |||||||||||||||||||||||||
| 250 | d// locked for write, assign a d_ptr and wait. | - | ||||||||||||||||||||||||
| 251 | auto val = QReadWriteLockPrivate::allocate(); | - | ||||||||||||||||||||||||
| 252 | val->readerWaitwriterCount = 1; | - | ||||||||||||||||||||||||
| 253 | if (!d_ptr
| 0-40 | ||||||||||||||||||||||||
--
| ||||||||||||||||||||||||||
| 254 | val->waitingReaderswriterCount = 0; | - | ||||||||||||||||||||||||
| 255 | val->release(); | - | ||||||||||||||||||||||||
| 256 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 257 | } | - | ||||||||||||||||||||||||
| 258 | d = val; | - | ||||||||||||||||||||||||
| 259 | } executed 40 times by 3 tests: end of blockExecuted by:
| 40 | ||||||||||||||||||||||||
| 260 | Q_ASSERT(!isUncontendedLocked(d)); | - | ||||||||||||||||||||||||
| 261 | // d is an actual pointer; | - | ||||||||||||||||||||||||
| 262 | - | |||||||||||||||||||||||||
| 263 | if (d->recursive)
| 126-132386 | ||||||||||||||||||||||||
| 264 | return d->currentReaders.insertrecursiveLockForRead(self, 1timeout); executed 126 times by 5 tests: return d->recursiveLockForRead(timeout);Executed by:
| 126 | ||||||||||||||||||||||||
| 265 | - | |||||||||||||||||||||||||
| 266 | ++dQMutexLocker lock(&d->accessCount; | - | ||||||||||||||||||||||||
| Q_ASSERT_Xmutex); | ||||||||||||||||||||||||||
| 267 | if
| 0-132386 | ||||||||||||||||||||||||
| 268 | // d_ptr has changed: this QReadWriteLock was unlocked before we had | - | ||||||||||||||||||||||||
| 269 | // time to lock d->mutex. | - | ||||||||||||||||||||||||
| 270 | // We are holding a lock to a mutex within a QReadWriteLockPrivate | - | ||||||||||||||||||||||||
| 271 | // that is already released (or even is already re-used). That's ok | - | ||||||||||||||||||||||||
| 272 | // because the QFreeList never frees them. | - | ||||||||||||||||||||||||
| 273 | // Just unlock d->mutex (at the end of the scope) and retry. | - | ||||||||||||||||||||||||
| 274 | d = d_ptr.loadAcquire(); | - | ||||||||||||||||||||||||
| 275 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 276 | } | - | ||||||||||||||||||||||||
| 277 | return executed 132386 times by 3 tests: d->accessCount > 0, "QReadWriteLock::lockForRead(timeout);return d->lockForRead(timeout);Executed by:
executed 132386 times by 3 tests: return d->lockForRead(timeout);Executed by:
| 132386 | ||||||||||||||||||||||||
| 278 | } | - | ||||||||||||||||||||||||
| 279 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 280 | - | |||||||||||||||||||||||||
| 281 | /*! | - | ||||||||||||||||||||||||
| 282 | Locks the lock for writing. This function will block the current | - | ||||||||||||||||||||||||
| 283 | thread if another thread (including the current) has locked for | - | ||||||||||||||||||||||||
| 284 | reading or writing (unless the lock has been created using the | - | ||||||||||||||||||||||||
| 285 | \l{QReadWriteLock::Recursive} mode). | - | ||||||||||||||||||||||||
| 286 | - | |||||||||||||||||||||||||
| 287 | It is not possible to lock for write if the thread already has | - | ||||||||||||||||||||||||
| 288 | locked for read. | - | ||||||||||||||||||||||||
| 289 | - | |||||||||||||||||||||||||
| 290 | \sa unlock(), lockForRead(), tryLockForWrite() | - | ||||||||||||||||||||||||
| 291 | */ | - | ||||||||||||||||||||||||
| 292 | void QReadWriteLock::lockForWrite() | - | ||||||||||||||||||||||||
| ", "Overflow in lock counter"{ | ||||||||||||||||||||||||||
| 294 | tryLockForWrite(-1); | - | ||||||||||||||||||||||||
| 295 | } executed 348346 times by 568 tests: end of blockExecuted by:
| 348346 | ||||||||||||||||||||||||
| 296 | - | |||||||||||||||||||||||||
| 297 | /*! | - | ||||||||||||||||||||||||
| 298 | Attempts to lock for writing. If the lock was obtained, this | - | ||||||||||||||||||||||||
| 299 | function returns \c true; otherwise, it returns \c false immediately. | - | ||||||||||||||||||||||||
| 300 | - | |||||||||||||||||||||||||
| 301 | The lock attempt will fail if another thread has locked for | - | ||||||||||||||||||||||||
| 302 | reading or writing. | - | ||||||||||||||||||||||||
| 303 | - | |||||||||||||||||||||||||
| 304 | If the lock was obtained, the lock must be unlocked with unlock() | - | ||||||||||||||||||||||||
| 305 | before another thread can successfully lock it. | - | ||||||||||||||||||||||||
| 306 | - | |||||||||||||||||||||||||
| 307 | It is not possible to lock for write if the thread already has | - | ||||||||||||||||||||||||
| 308 | locked for read. | - | ||||||||||||||||||||||||
| 309 | - | |||||||||||||||||||||||||
| 310 | \sa unlock(), lockForWrite() | - | ||||||||||||||||||||||||
| 311 | */ | - | ||||||||||||||||||||||||
| 312 | bool QReadWriteLock::tryLockForReadtryLockForWrite() | - | ||||||||||||||||||||||||
| 313 | { | - | ||||||||||||||||||||||||
| 314 | QMutexLocker lockreturn tryLockForWrite(&d->mutex0); executed 62 times by 4 tests: return tryLockForWrite(0);Executed by:
| 62 | ||||||||||||||||||||||||
| Qt} | ||||||||||||||||||||||||||
| 316 | - | |||||||||||||||||||||||||
| 317 | /*! \overload | - | ||||||||||||||||||||||||
| 318 | - | |||||||||||||||||||||||||
| 319 | Attempts to lock for writing. This function returns \c true if the | - | ||||||||||||||||||||||||
| 320 | lock was obtained; otherwise it returns \c false. If another thread | - | ||||||||||||||||||||||||
| 321 | has locked for reading or writing, this function will wait for at | - | ||||||||||||||||||||||||
| 322 | most \a timeout milliseconds for the lock to become available. | - | ||||||||||||||||||||||||
| 323 | - | |||||||||||||||||||||||||
| 324 | Note: Passing a negative number as the \a timeout is equivalent to | - | ||||||||||||||||||||||||
| 325 | calling lockForWrite(), i.e. this function will wait forever until | - | ||||||||||||||||||||||||
| 326 | lock can be locked for writing when \a timeout is negative. | - | ||||||||||||||||||||||||
| 327 | - | |||||||||||||||||||||||||
| 328 | If the lock was obtained, the lock must be unlocked with unlock() | - | ||||||||||||||||||||||||
| 329 | before another thread can successfully lock it. | - | ||||||||||||||||||||||||
| 330 | - | |||||||||||||||||||||||||
| 331 | It is not possible to lock for write if the thread already has | - | ||||||||||||||||||||||||
| 332 | locked for read. | - | ||||||||||||||||||||||||
| 333 | - | |||||||||||||||||||||||||
| 334 | \sa unlock(), lockForWrite() | - | ||||||||||||||||||||||||
| 335 | */ | - | ||||||||||||||||||||||||
| 336 | bool QReadWriteLock::HANDLE self = 0; | - | ||||||||||||||||||||||||
| iftryLockForWrite(d->recursiveint timeout) | ||||||||||||||||||||||||||
| 337 | { | - | ||||||||||||||||||||||||
| 338 | self = QThread::currentThreadId(); | - | ||||||||||||||||||||||||
| QHash<Qt::HANDLE, int>::iterator it =// Fast case: non contended: | ||||||||||||||||||||||||||
| 339 | QReadWriteLockPrivate *d->currentReaders; | - | ||||||||||||||||||||||||
| 340 | if (d_ptr
| 3057-345353 | ||||||||||||||||||||||||
| 341 | return true; executed 345353 times by 565 tests: return true;Executed by:
| 345353 | ||||||||||||||||||||||||
| 342 | - | |||||||||||||||||||||||||
| 343 | while (true) { | - | ||||||||||||||||||||||||
| 344 | if (it !=d ->currentReaders.end())== 0) {
| 0-3057 | ||||||||||||||||||||||||
| 345 | ++itif (!d_ptr.value();
| 0 | ||||||||||||||||||||||||
++d->accessCount;
| ||||||||||||||||||||||||||
Q_ASSERT_X
| ||||||||||||||||||||||||||
"Overflow in lock counter");
| ||||||||||||||||||||||||||
| 346 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 347 | return true; never executed: return true; | 0 | ||||||||||||||||||||||||
| 348 | }} | - | ||||||||||||||||||||||||
| 349 | - | |||||||||||||||||||||||||
| 350 | if (isUncontendedLocked(d->accessCount < 0)) {
| 88-2969 | ||||||||||||||||||||||||
| 351 | if (!timeout
| 10-78 | ||||||||||||||||||||||||
| 352 | return false; executed 10 times by 3 tests: return false;Executed by:
| 10 | ||||||||||||||||||||||||
| 353 | - | |||||||||||||||||||||||||
| 354 | // locked for either read or write, assign a d_ptr and wait. | - | ||||||||||||||||||||||||
| 355 | auto val = QReadWriteLockPrivate::allocate(); | - | ||||||||||||||||||||||||
| 356 | if (d ->recursive== dummyLockedForWrite)
| 24-54 | ||||||||||||||||||||||||
| 357 | dval->currentReaders.insert(self,writerCount = 1); executed 54 times by 3 tests: val->writerCount = 1;Executed by:
| 54 | ||||||||||||||||||||||||
| ++d executed 54 times by 3 tests: ;val->writerCount = 1;Executed by:
executed 54 times by 3 tests: val->writerCount = 1;Executed by:
| ||||||||||||||||||||||||||
| 358 | else | - | ||||||||||||||||||||||||
| 359 | val executed 24 times by 3 tests: ->accessCountreaderCount = (quintptr(d) >> 4) + 1;val->readerCount = (quintptr(d) >> 4) + 1;Executed by:
executed 24 times by 3 tests: val->readerCount = (quintptr(d) >> 4) + 1;Executed by:
| 24 | ||||||||||||||||||||||||
| 360 | Q_ASSERT_Xif (!d_ptr.testAndSetOrdered(d->accessCount > 0, "QReadWriteLock::tryLockForRead()"val, "Overflow in lock counter");
| 0-78 | ||||||||||||||||||||||||
return true;
| ||||||||||||||||||||||||||
}
| ||||||||||||||||||||||||||
bool QReadWriteLock::tryLockForRead(int timeout)
| ||||||||||||||||||||||||||
| 361 | QMutexLocker lock(&dval->mutex); | - | ||||||||||||||||||||||||
| Qt::HANDLE selfwriterCount = val->readerCount = 0; | ||||||||||||||||||||||||||
| 362 | val->release(); | - | ||||||||||||||||||||||||
| 363 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 364 | } | - | ||||||||||||||||||||||||
| 365 | d = val; | - | ||||||||||||||||||||||||
| 366 | } executed 78 times by 3 tests: end of blockExecuted by:
| 78 | ||||||||||||||||||||||||
| 367 | Q_ASSERT(!isUncontendedLocked(d)); | - | ||||||||||||||||||||||||
| 368 | // d is an actual pointer; | - | ||||||||||||||||||||||||
| 369 | - | |||||||||||||||||||||||||
| 370 | if (d->recursive)
| 76-2971 | ||||||||||||||||||||||||
| 371 | { executed 76 times by 8 tests: return d->recursiveLockForWrite(timeout);Executed by:
| 76 | ||||||||||||||||||||||||
| self = QThread::currentThreadId(); executed 76 times by 8 tests: return d->recursiveLockForWrite(timeout);Executed by:
| ||||||||||||||||||||||||||
| QHash<Qt::HANDLE, int>::iterator it = executed 76 times by 8 tests: return d->currentReaders.findrecursiveLockForWrite(selftimeout);return d->recursiveLockForWrite(timeout);Executed by:
executed 76 times by 8 tests: return d->recursiveLockForWrite(timeout);Executed by:
| ||||||||||||||||||||||||||
| 372 | - | |||||||||||||||||||||||||
| 373 | QMutexLocker lock(&d->mutex); | - | ||||||||||||||||||||||||
| 374 | if (it !=d ->currentReaders!= d_ptr.endload()) {
| 0-2971 | ||||||||||||||||||||||||
| 375 | ++it// The mutex was unlocked before we had time to lock the mutex. | - | ||||||||||||||||||||||||
| 376 | // We are holding to a mutex within a QReadWriteLockPrivate that is already released | - | ||||||||||||||||||||||||
| 377 | // (or even is already re-used) but that's ok because the QFreeList never frees them. | - | ||||||||||||||||||||||||
| 378 | d = d_ptr.valueloadAcquire(); | - | ||||||||||||||||||||||||
| 379 | ++continue; never executed: continue; | 0 | ||||||||||||||||||||||||
| 380 | } | - | ||||||||||||||||||||||||
| 381 | return executed 2971 times by 3 tests: d->accessCount;lockForWrite(timeout);return d->lockForWrite(timeout);Executed by:
executed 2971 times by 3 tests: return d->lockForWrite(timeout);Executed by:
| 2971 | ||||||||||||||||||||||||
| 382 | } | - | ||||||||||||||||||||||||
| 383 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 384 | - | |||||||||||||||||||||||||
| 385 | /*! | - | ||||||||||||||||||||||||
| 386 | Unlocks the lock. | - | ||||||||||||||||||||||||
| 387 | - | |||||||||||||||||||||||||
| 388 | Attempting to unlock a lock that is not locked is an error, and will result | - | ||||||||||||||||||||||||
| 389 | in program termination. | - | ||||||||||||||||||||||||
| 390 | - | |||||||||||||||||||||||||
| 391 | \sa lockForRead(), lockForWrite(), tryLockForRead(), tryLockForWrite() | - | ||||||||||||||||||||||||
| 392 | */ | - | ||||||||||||||||||||||||
| 393 | void QReadWriteLock::unlock() | - | ||||||||||||||||||||||||
| 394 | { | - | ||||||||||||||||||||||||
| 395 | QReadWriteLockPrivate *d = d_ptr.load(); | - | ||||||||||||||||||||||||
| 396 | while (true) { | - | ||||||||||||||||||||||||
| 397 | Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForReadunlock()", | - | ||||||||||||||||||||||||
| "Overflow in"Cannot lockunlock counter"an unlocked lock"); | ||||||||||||||||||||||||||
| 398 | - | |||||||||||||||||||||||||
| 399 | // Fast case: no contention: (no waiters, no other readers) | - | ||||||||||||||||||||||||
| 400 |
| 146830-1902811 | ||||||||||||||||||||||||
| 401 |
| 1-1902810 | ||||||||||||||||||||||||
| 402 | continue; executed 1 time by 1 test: continue;Executed by:
| 1 | ||||||||||||||||||||||||
| 403 | returntrue; executed 1902810 times by 572 tests: return;Executed by:
| 1902810 | ||||||||||||||||||||||||
| 404 | }} | - | ||||||||||||||||||||||||
| 405 | - | |||||||||||||||||||||||||
| 406 | whileif ((quintptr(d->accessCount < 0 ||d->waitingWriters) & StateMask) == StateLockedForRead) {
| 11197-135633 | ||||||||||||||||||||||||
| 407 | ++Q_ASSERT(quintptr(d->waitingReaders; | - | ||||||||||||||||||||||||
| bool success) > (1U<<4)); //otherwise that would be the fast case | ||||||||||||||||||||||||||
| 408 | // Just decrease the reader's count. | - | ||||||||||||||||||||||||
| 409 | auto val = reinterpret_cast<QReadWriteLockPrivate *>(quintptr(d->readerWait) - (1U<<4)); | - | ||||||||||||||||||||||||
| 410 | if (!d_ptr
| 0-11197 | ||||||||||||||||||||||||
--
| ||||||||||||||||||||||||||
| 411 | continue never executed: ;continue;never executed: continue; | 0 | ||||||||||||||||||||||||
| 412 | if (!success)returnfalse; executed 11197 times by 6 tests: return;Executed by:
| 11197 | ||||||||||||||||||||||||
| 413 | } | - | ||||||||||||||||||||||||
| 414 | - | |||||||||||||||||||||||||
| 415 | Q_ASSERT(!isUncontendedLocked(d)); | - | ||||||||||||||||||||||||
| 416 | - | |||||||||||||||||||||||||
| 417 | if (d->recursive) d->currentReaders.insert(self, 1);
| 159-135474 | ||||||||||||||||||||||||
++d->accessCount;
| ||||||||||||||||||||||||||
Q_ASSERT_X(
| ||||||||||||||||||||||||||
| 418 | d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter");recursiveUnlock(); | - | ||||||||||||||||||||||||
| 419 | returntrue; executed 159 times by 8 tests: return;Executed by:
| 159 | ||||||||||||||||||||||||
| 420 | } | - | ||||||||||||||||||||||||
| 421 | - | |||||||||||||||||||||||||
| 422 | void QReadWriteLock::lockForWrite() | - | ||||||||||||||||||||||||
| {QMutexLocker locklocker(&d->mutex); | ||||||||||||||||||||||||||
| 423 | Qt::HANDLE self = 0;if (d->recursivewriterCount) {
| 3064-132410 | ||||||||||||||||||||||||
| 424 | self = QThread::currentThreadId(); | - | ||||||||||||||||||||||||
| ifQ_ASSERT(d->currentWriterwriterCount == self) { | ||||||||||||||||||||||||||
| --1); | ||||||||||||||||||||||||||
| 425 | Q_ASSERT(d->accessCountreaderCount == 0); | - | ||||||||||||||||||||||||
| 426 | d->writerCount = 0; | - | ||||||||||||||||||||||||
| 427 | Q_ASSERT_X} else { executed 3064 times by 3 tests: end of blockExecuted by:
| 3064 | ||||||||||||||||||||||||
| 428 | Q_ASSERT(d->accessCount <readerCount > 0, "QReadWriteLock::lockForWrite()", | - | ||||||||||||||||||||||||
| "Overflow in lock counter"); | ||||||||||||||||||||||||||
| 429 | d->readerCount--; | - | ||||||||||||||||||||||||
| 430 | if (d->readerCount > 0)
| 265-132145 | ||||||||||||||||||||||||
| 431 | return; executed 132145 times by 1 test: return;Executed by:
| 132145 | ||||||||||||||||||||||||
| 432 | }} executed 265 times by 3 tests: end of blockExecuted by:
| 265 | ||||||||||||||||||||||||
| 433 | - | |||||||||||||||||||||||||
| 434 | whileif (d->accessCount != 0) {
| 118-3002 | ||||||||||||||||||||||||
++
| ||||||||||||||||||||||||||
| 435 | d->writerWaitunlock(); | - | ||||||||||||||||||||||||
| 436 | } else { executed 3211 times by 3 tests: end of blockExecuted by:
| 3211 | ||||||||||||||||||||||||
| 437 | Q_ASSERT(d_ptr.waitload() == d); // should not change when we still hold the mutex | - | ||||||||||||||||||||||||
| 438 | d_ptr.storeRelease(&d->mutexnullptr); | - | ||||||||||||||||||||||||
| 439 | --d->waitingWritersrelease(); | - | ||||||||||||||||||||||||
| 440 | } executed 118 times by 3 tests: end of blockExecuted by:
| 118 | ||||||||||||||||||||||||
| 441 | return executed 3329 times by 3 tests: ;return;Executed by:
executed 3329 times by 3 tests: return;Executed by:
| 3329 | ||||||||||||||||||||||||
| 442 | } | - | ||||||||||||||||||||||||
| if never executed: }end of blocknever executed: end of block | ||||||||||||||||||||||||||
| 444 | - | |||||||||||||||||||||||||
| 445 | /*! \internal Helper for QWaitCondition::wait */ | - | ||||||||||||||||||||||||
| 446 | QReadWriteLock::StateForWaitCondition QReadWriteLock::stateForWaitCondition() const | - | ||||||||||||||||||||||||
| 447 | { | - | ||||||||||||||||||||||||
| 448 | QReadWriteLockPrivate *d = d_ptr.load(); | - | ||||||||||||||||||||||||
| 449 | switch (quintptr(d->recursive) & StateMask) { | - | ||||||||||||||||||||||||
| 450 | case StateLockedForRead: return LockedForRead; executed 25 times by 1 test: return LockedForRead;Executed by:
executed 25 times by 1 test: case StateLockedForRead:Executed by:
| 25 | ||||||||||||||||||||||||
| 451 | case StateLockedForWrite: return LockedForWrite; executed 108 times by 1 test: return LockedForWrite;Executed by:
executed 108 times by 1 test: case StateLockedForWrite:Executed by:
| 108 | ||||||||||||||||||||||||
| 452 | } | - | ||||||||||||||||||||||||
| 453 | - | |||||||||||||||||||||||||
| 454 | if (!
| 0-141 | ||||||||||||||||||||||||
| 455 | return Unlocked never executed: ;return Unlocked;never executed: return Unlocked; | 0 | ||||||||||||||||||||||||
| 456 | --if (d->accessCountwriterCount > 1)
| 0-141 | ||||||||||||||||||||||||
| 457 | return RecursivelyLocked never executed: ;return RecursivelyLocked;never executed: return RecursivelyLocked; | 0 | ||||||||||||||||||||||||
| 458 | Q_ASSERT_Xelse if (d->accessCount < 0, "QReadWriteLock::lockForWrite()", "Overflow in lock counter");writerCount == 1)
| 18-123 | ||||||||||||||||||||||||
| 459 | return LockedForWrite; executed 123 times by 1 test: return LockedForWrite;Executed by:
| 123 | ||||||||||||||||||||||||
| 460 | return LockedForRead; executed 18 times by 1 test: return LockedForRead;Executed by:
| 18 | ||||||||||||||||||||||||
| 461 | - | |||||||||||||||||||||||||
| 462 | } | - | ||||||||||||||||||||||||
| 463 | - | |||||||||||||||||||||||||
| 464 | bool QReadWriteLockQReadWriteLockPrivate::tryLockForWrite() | - | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| QMutexLocker locklockForRead(&d->int timeout) | ||||||||||||||||||||||||||
| 465 | { | - | ||||||||||||||||||||||||
| 466 | Q_ASSERT(!mutex); | - | ||||||||||||||||||||||||
| Qt::HANDLE self =.tryLock()); // mutex must be locked when entering this function | ||||||||||||||||||||||||||
| 467 | - | |||||||||||||||||||||||||
| 468 | QElapsedTimer t; | - | ||||||||||||||||||||||||
| 469 | if (timeout > 0)
| 1-132492 | ||||||||||||||||||||||||
| 470 | t.start(); executed 1 time by 1 test: t.start();Executed by:
| 1 | ||||||||||||||||||||||||
| 471 | - | |||||||||||||||||||||||||
| 472 | while (waitingWriters || writerCount) {
| 72-132543 | ||||||||||||||||||||||||
| 473 | if (timeout ==
| 21-437 | ||||||||||||||||||||||||
| 474 | return false executed 21 times by 2 tests: ;return false;Executed by:
executed 21 times by 2 tests: return false;Executed by:
| 21 | ||||||||||||||||||||||||
| 475 | if (d->recursivetimeout > 0) {
| 8-429 | ||||||||||||||||||||||||
| 476 | selfauto elapsed = QThread::currentThreadIdt.elapsed(); | - | ||||||||||||||||||||||||
| 477 | if (d->currentWriter == selfelapsed > timeout)
| 1-7 | ||||||||||||||||||||||||
| 478 | { executed 1 time by 1 test: return false;Executed by:
| 1 | ||||||||||||||||||||||||
| --d->accessCount executed 1 time by 1 test: return false;return false;Executed by:
executed 1 time by 1 test: return false;Executed by:
| ||||||||||||||||||||||||||
| 479 | Q_ASSERT_XwaitingReaders++; | - | ||||||||||||||||||||||||
| 480 | readerCond.wait(d->accessCount < 0, "QReadWriteLock::lockForWrite()"&mutex, | - | ||||||||||||||||||||||||
| "Overflow in lock counter"timeout - elapsed); | ||||||||||||||||||||||||||
| 481 | } else { executed 7 times by 1 test: end of blockExecuted by:
| 7 | ||||||||||||||||||||||||
| 482 | waitingReaders++; | - | ||||||||||||||||||||||||
| 483 | readerCond.wait(&mutex); | - | ||||||||||||||||||||||||
| 484 | } executed 429 times by 3 tests: end of blockExecuted by:
| 429 | ||||||||||||||||||||||||
| 485 | waitingReaders--; | - | ||||||||||||||||||||||||
| 486 | } executed 436 times by 3 tests: end of blockExecuted by:
| 436 | ||||||||||||||||||||||||
| 487 | readerCount++; | - | ||||||||||||||||||||||||
| 488 | Q_ASSERT(writerCount == 0); | - | ||||||||||||||||||||||||
| 489 | return true; executed 132471 times by 6 tests: return true;Executed by:
| 132471 | ||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||
| 491 | - | |||||||||||||||||||||||||
| 492 | bool QReadWriteLockPrivate::lockForWrite(int timeout) | - | ||||||||||||||||||||||||
| 493 | { | - | ||||||||||||||||||||||||
| 494 | Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function | - | ||||||||||||||||||||||||
| 495 | - | |||||||||||||||||||||||||
| 496 | QElapsedTimer t; | - | ||||||||||||||||||||||||
| 497 | if (d->accessCount !=timeout > 0)
| 1-3034 | ||||||||||||||||||||||||
| 498 | t.start(); executed 1 time by 1 test: t.start();Executed by:
| 1 | ||||||||||||||||||||||||
| 499 | - | |||||||||||||||||||||||||
| 500 | while (readerCount || writerCount) {
| 74-3276 | ||||||||||||||||||||||||
| 501 | if (timeout ==
| 22-316 | ||||||||||||||||||||||||
| 502 | return false; executed 22 times by 2 tests: return false;Executed by:
| 22 | ||||||||||||||||||||||||
| 503 | if (d->recursivetimeout > 0) d->currentWriter{
| 8-308 | ||||||||||||||||||||||||
| 504 | auto elapsed = self; | - | ||||||||||||||||||||||||
| --d->accessCountt.elapsed(); | ||||||||||||||||||||||||||
| 505 | if (elapsed > timeout) {
| 1-7 | ||||||||||||||||||||||||
| 506 | if (waitingReaders && !waitingWriters && !writerCount) {
| 0-1 | ||||||||||||||||||||||||
| 507 | // We timed out and now there is no more writers or waiting writers, but some | - | ||||||||||||||||||||||||
| 508 | // readers were queueud (probably because of us). Wake the waiting readers. | - | ||||||||||||||||||||||||
| 509 | readerCond.wakeAll(); | - | ||||||||||||||||||||||||
| 510 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 511 | return false executed 1 time by 1 test: ;return false;Executed by:
executed 1 time by 1 test: return false;Executed by:
| 1 | ||||||||||||||||||||||||
| 512 | Q_ASSERT_X} | - | ||||||||||||||||||||||||
| 513 | waitingWriters++; | - | ||||||||||||||||||||||||
| 514 | writerCond.wait(d->accessCount < 0, "QReadWriteLock::tryLockForWrite()"&mutex, | - | ||||||||||||||||||||||||
| "Overflow in lock counter"timeout - elapsed); | ||||||||||||||||||||||||||
| 515 | } else { executed 7 times by 1 test: end of blockExecuted by:
| 7 | ||||||||||||||||||||||||
| 516 | waitingWriters++; | - | ||||||||||||||||||||||||
| 517 | writerCond.wait(&mutex); | - | ||||||||||||||||||||||||
| 518 | } executed 308 times by 3 tests: end of blockExecuted by:
| 308 | ||||||||||||||||||||||||
| 519 | waitingWriters--; | - | ||||||||||||||||||||||||
| 520 | } executed 315 times by 3 tests: end of blockExecuted by:
| 315 | ||||||||||||||||||||||||
| 521 | - | |||||||||||||||||||||||||
| 522 | Q_ASSERT(writerCount == 0); | - | ||||||||||||||||||||||||
| 523 | Q_ASSERT(readerCount == 0); | - | ||||||||||||||||||||||||
| 524 | writerCount = 1; | - | ||||||||||||||||||||||||
| 525 | return true; executed 3012 times by 9 tests: return true;Executed by:
| 3012 | ||||||||||||||||||||||||
| 526 | } | - | ||||||||||||||||||||||||
| 527 | - | |||||||||||||||||||||||||
| 528 | void QReadWriteLockPrivate::unlock() | - | ||||||||||||||||||||||||
| 529 | { | - | ||||||||||||||||||||||||
| 530 | Q_ASSERT(!mutex.tryLock()); // mutex must be locked when entering this function | - | ||||||||||||||||||||||||
| 531 |
| 417-2922 | ||||||||||||||||||||||||
| 532 | writerCond.wakeOne(); executed 2922 times by 3 tests: writerCond.wakeOne();Executed by:
| 2922 | ||||||||||||||||||||||||
| 533 | else if (waitingReaders)
| 127-290 | ||||||||||||||||||||||||
| 534 | readerCond.wakeAll(); executed 290 times by 3 tests: readerCond.wakeAll();Executed by:
| 290 | ||||||||||||||||||||||||
| 535 | } executed 3339 times by 9 tests: end of blockExecuted by:
| 3339 | ||||||||||||||||||||||||
| 536 | - | |||||||||||||||||||||||||
| 537 | bool QReadWriteLockQReadWriteLockPrivate::tryLockForWriterecursiveLockForRead(int timeout) | - | ||||||||||||||||||||||||
| 538 | { | - | ||||||||||||||||||||||||
| 539 | Q_ASSERT(recursive); | - | ||||||||||||||||||||||||
| 540 | QMutexLocker lock(&d->mutex&mutex); | - | ||||||||||||||||||||||||
| 541 | - | |||||||||||||||||||||||||
| 542 | Qt::HANDLE self = 0; | - | ||||||||||||||||||||||||
| if (d->recursive) {self = QThread::currentThreadId(); | ||||||||||||||||||||||||||
| 543 | - | |||||||||||||||||||||||||
| 544 | ifauto it = currentReaders.find(d->currentWriter ==self)); | - | ||||||||||||||||||||||||
| 545 | if (it != currentReaders.end())
| 19-107 | ||||||||||||||||||||||||
| 546 | --d->accessCount++it.value(); | - | ||||||||||||||||||||||||
| 547 | return true executed 19 times by 4 tests: ;return true;Executed by:
executed 19 times by 4 tests: return true;Executed by:
| 19 | ||||||||||||||||||||||||
| 548 | Q_ASSERT_X} | - | ||||||||||||||||||||||||
| 549 | - | |||||||||||||||||||||||||
| 550 | if (!lockForRead
| 21-86 | ||||||||||||||||||||||||
| 551 | return false; executed 21 times by 2 tests: return false;Executed by:
| 21 | ||||||||||||||||||||||||
| 552 | - | |||||||||||||||||||||||||
| 553 | currentReaders.insert(self, | - | ||||||||||||||||||||||||
| "Overflow in lock counter"1); | ||||||||||||||||||||||||||
| 554 | return true; executed 86 times by 5 tests: return true;Executed by:
| 86 | ||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||
| 556 | - | |||||||||||||||||||||||||
| whilebool QReadWriteLockPrivate::recursiveLockForWrite(d->accessCount != 0int timeout) | ||||||||||||||||||||||||||
| 558 | { | - | ||||||||||||||||||||||||
| 559 | ++d->waitingWriters; | - | ||||||||||||||||||||||||
| bool success = d->writerWait.waitQ_ASSERT(&d->mutex, timeout < 0 ? ULONG_MAX : ulongrecursive); | ||||||||||||||||||||||||||
| 560 | QMutexLocker lock(timeout)); | - | ||||||||||||||||||||||||
| --d->waitingWriters;&mutex); | ||||||||||||||||||||||||||
| 561 | - | |||||||||||||||||||||||||
| 562 | Qt::HANDLE self = QThread::currentThreadId(); | - | ||||||||||||||||||||||||
| 563 | if (!success(currentWriter == self) {
| 12-64 | ||||||||||||||||||||||||
| 564 | writerCount++; | - | ||||||||||||||||||||||||
| 565 | return falsetrue; executed 12 times by 2 tests: return true;Executed by:
| 12 | ||||||||||||||||||||||||
| 566 | } | - | ||||||||||||||||||||||||
| 567 | - | |||||||||||||||||||||||||
| 568 | if (!lockForWrite(d->recursive)
| 22-42 | ||||||||||||||||||||||||
d->
| ||||||||||||||||||||||||||
| 569 | return false; executed 22 times by 2 tests: return false;Executed by:
| 22 | ||||||||||||||||||||||||
| 570 | - | |||||||||||||||||||||||||
| 571 | currentWriter = self; | - | ||||||||||||||||||||||||
| --d->accessCount; | ||||||||||||||||||||||||||
| 572 | Q_ASSERT_X(d->accessCount < 0, "QReadWriteLock::tryLockForWrite()", executed 42 times by 8 tests: return true;Executed by:
| 42 | ||||||||||||||||||||||||
| "Overflow in lock counter"); executed 42 times by 8 tests: return true;return true;Executed by:
executed 42 times by 8 tests: return true;Executed by:
| ||||||||||||||||||||||||||
| 573 | } | - | ||||||||||||||||||||||||
| 574 | - | |||||||||||||||||||||||||
| 575 | void QReadWriteLockQReadWriteLockPrivate::unlockrecursiveUnlock() | - | ||||||||||||||||||||||||
| 576 | { | - | ||||||||||||||||||||||||
| 577 | QMutexLocker lockQ_ASSERT(&d->mutexrecursive); | - | ||||||||||||||||||||||||
| 578 | Q_ASSERT_XQMutexLocker lock(d->accessCount != 0, "QReadWriteLock::unlock()", "Cannot unlock an unlocked lock"&mutex); | - | ||||||||||||||||||||||||
| 579 | - | |||||||||||||||||||||||||
| 580 | bool unlocked = false; | - | ||||||||||||||||||||||||
| if (d->accessCount > 0) { | ||||||||||||||||||||||||||
| if (d->recursive) {Qt::HANDLE self = QThread::currentThreadId(); | ||||||||||||||||||||||||||
| 581 | QHash<Qt::HANDLE, int>::iteratorif (self == currentWriter) {
| 54-105 | ||||||||||||||||||||||||
| 582 | if (--writerCount > 0)
| 12-42 | ||||||||||||||||||||||||
| 583 | return; executed 12 times by 2 tests: return;Executed by:
| 12 | ||||||||||||||||||||||||
| 584 | currentWriter = 0; | - | ||||||||||||||||||||||||
| 585 | } else { executed 42 times by 8 tests: end of blockExecuted by:
| 42 | ||||||||||||||||||||||||
| 586 | auto it = d->currentReaders.find(self); | - | ||||||||||||||||||||||||
| 587 | if (it != d->== currentReaders.end()) {
| 0-105 | ||||||||||||||||||||||||
| 588 | qWarning("QReadWriteLock::unlock: unlocking from a thread that did not lock"); | - | ||||||||||||||||||||||||
| 589 | return; never executed: return; | 0 | ||||||||||||||||||||||||
| 590 | } else { | - | ||||||||||||||||||||||||
| 591 | if (--it.value() <= 0) d->{
| 19-86 | ||||||||||||||||||||||||
| 592 | currentReaders.erase(it); | - | ||||||||||||||||||||||||
| 593 | readerCount--; | - | ||||||||||||||||||||||||
| 594 | } executed 86 times by 5 tests: end of blockExecuted by:
| 86 | ||||||||||||||||||||||||
| 595 | if (readerCount)
| 19-86 | ||||||||||||||||||||||||
| 596 | return; executed 19 times by 4 tests: return;Executed by:
| 19 | ||||||||||||||||||||||||
| 597 | } executed 86 times by 5 tests: end of blockExecuted by:
| 86 | ||||||||||||||||||||||||
| 598 | unlocked} | - | ||||||||||||||||||||||||
| 599 | - | |||||||||||||||||||||||||
| 600 | unlock(); | - | ||||||||||||||||||||||||
| 601 | } executed 128 times by 8 tests: end of blockExecuted by:
| 128 | ||||||||||||||||||||||||
| 602 | - | |||||||||||||||||||||||||
| 603 | // The freelist management | - | ||||||||||||||||||||||||
| 604 | namespace { | - | ||||||||||||||||||||||||
| 605 | struct FreeListConstants : QFreeListDefaultConstants { | - | ||||||||||||||||||||||||
| 606 | enum { BlockCount = --d->accessCount == 04, MaxIndex=0xffff }; | - | ||||||||||||||||||||||||
| 607 | static const int Sizes[BlockCount]; | - | ||||||||||||||||||||||||
| 608 | }; | - | ||||||||||||||||||||||||
| 609 | const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = { | - | ||||||||||||||||||||||||
| 610 | 16, | - | ||||||||||||||||||||||||
| 611 | 128, | - | ||||||||||||||||||||||||
| 612 | 1024, | - | ||||||||||||||||||||||||
| 613 | FreeListConstants::MaxIndex - (16 + 128 + 1024) | - | ||||||||||||||||||||||||
| 614 | }; | - | ||||||||||||||||||||||||
| 615 | - | |||||||||||||||||||||||||
| 616 | typedef QFreeList<QReadWriteLockPrivate, FreeListConstants> FreeList; | - | ||||||||||||||||||||||||
| } else if executed 3 times by 3 tests: end of blockExecuted by:
executed 3 times by 3 tests: guard.store(QtGlobalStatic::Destroyed);Executed by:
executed 354 times by 3 tests: return &holder.value;Executed by:
executed 3 times by 3 tests: end of blockExecuted by:
executed 3 times by 3 tests: guard.store(QtGlobalStatic::Destroyed);Executed by:
executed 354 times by 3 tests: return &holder.value;Executed by:
| ||||||||||||||||||||||||||
| 618 | } | - | ||||||||||||||||||||||||
| 619 | - | |||||||||||||||||||||||||
| 620 | QReadWriteLockPrivate *QReadWriteLockPrivate::allocate() | - | ||||||||||||||||||||||||
| 621 | { | - | ||||||||||||||||||||||||
| 622 | int i = freelist->accessCount < 0 && ++next(); | - | ||||||||||||||||||||||||
| 623 | QReadWriteLockPrivate *d ->accessCount == 0) { | - | ||||||||||||||||||||||||
| unlocked= true;&(*freelist)[i]; | ||||||||||||||||||||||||||
| 624 | d->currentWriterid = 0i; | - | ||||||||||||||||||||||||
| 625 | } | - | ||||||||||||||||||||||||
| if (unlocked) { | ||||||||||||||||||||||||||
| if (Q_ASSERT(!d->waitingWriters) {recursive); | ||||||||||||||||||||||||||
| 626 | Q_ASSERT(!d->writerWait.wakeOne(); | - | ||||||||||||||||||||||||
| } else if (waitingReaders && !d->waitingReaders ) {&& !d->readerWait.wakeAll(); | ||||||||||||||||||||||||||
| }readerCount && !d->writerCount); | ||||||||||||||||||||||||||
| 627 | return d; executed 118 times by 3 tests: return d;Executed by:
| 118 | ||||||||||||||||||||||||
| 628 | } | - | ||||||||||||||||||||||||
| 629 | - | |||||||||||||||||||||||||
| 630 | void QReadWriteLockPrivate::release() | - | ||||||||||||||||||||||||
| 631 | { | - | ||||||||||||||||||||||||
| 632 | Q_ASSERT(!recursive); | - | ||||||||||||||||||||||||
| 633 | Q_ASSERT(!waitingReaders && !waitingReaders && !readerCount && !writerCount); | - | ||||||||||||||||||||||||
| 634 | freelist->release(id); | - | ||||||||||||||||||||||||
| 635 | } executed 118 times by 3 tests: end of blockExecuted by:
| 118 | ||||||||||||||||||||||||
| 636 | - | |||||||||||||||||||||||||
| 637 | /*! | - | ||||||||||||||||||||||||
| 638 | \class QReadLocker | - | ||||||||||||||||||||||||
| 639 | \inmodule QtCore | - | ||||||||||||||||||||||||
| 640 | \brief The QReadLocker class is a convenience class that | - | ||||||||||||||||||||||||
| 641 | simplifies locking and unlocking read-write locks for read access. | - | ||||||||||||||||||||||||
| 642 | - | |||||||||||||||||||||||||
| 643 | \threadsafe | - | ||||||||||||||||||||||||
| 644 | - | |||||||||||||||||||||||||
| 645 | \ingroup thread | - | ||||||||||||||||||||||||
| 646 | - | |||||||||||||||||||||||||
| 647 | The purpose of QReadLocker (and QWriteLocker) is to simplify | - | ||||||||||||||||||||||||
| 648 | QReadWriteLock locking and unlocking. Locking and unlocking | - | ||||||||||||||||||||||||
| 649 | statements or in exception handling code is error-prone and | - | ||||||||||||||||||||||||
| 650 | difficult to debug. QReadLocker can be used in such situations | - | ||||||||||||||||||||||||
| 651 | to ensure that the state of the lock is always well-defined. | - | ||||||||||||||||||||||||
| 652 | - | |||||||||||||||||||||||||
| 653 | Here's an example that uses QReadLocker to lock and unlock a | - | ||||||||||||||||||||||||
| 654 | read-write lock for reading: | - | ||||||||||||||||||||||||
| 655 | - | |||||||||||||||||||||||||
| 656 | \snippet code/src_corelib_thread_qreadwritelock.cpp 1 | - | ||||||||||||||||||||||||
| 657 | - | |||||||||||||||||||||||||
| 658 | It is equivalent to the following code: | - | ||||||||||||||||||||||||
| 659 | - | |||||||||||||||||||||||||
| 660 | \snippet code/src_corelib_thread_qreadwritelock.cpp 2 | - | ||||||||||||||||||||||||
| 661 | - | |||||||||||||||||||||||||
| 662 | The QMutexLocker documentation shows examples where the use of a | - | ||||||||||||||||||||||||
| 663 | locker object greatly simplifies programming. | - | ||||||||||||||||||||||||
| 664 | - | |||||||||||||||||||||||||
| 665 | \sa QWriteLocker, QReadWriteLock | - | ||||||||||||||||||||||||
| 666 | */ | - | ||||||||||||||||||||||||
| 667 | - | |||||||||||||||||||||||||
| 668 | /*! | - | ||||||||||||||||||||||||
| 669 | \fn QReadLocker::QReadLocker(QReadWriteLock *lock) | - | ||||||||||||||||||||||||
| 670 | - | |||||||||||||||||||||||||
| 671 | Constructs a QReadLocker and locks \a lock for reading. The lock | - | ||||||||||||||||||||||||
| 672 | will be unlocked when the QReadLocker is destroyed. If \c lock is | - | ||||||||||||||||||||||||
| 673 | zero, QReadLocker does nothing. | - | ||||||||||||||||||||||||
| 674 | - | |||||||||||||||||||||||||
| 675 | \sa QReadWriteLock::lockForRead() | - | ||||||||||||||||||||||||
| 676 | */ | - | ||||||||||||||||||||||||
| 677 | - | |||||||||||||||||||||||||
| 678 | /*! | - | ||||||||||||||||||||||||
| 679 | \fn QReadLocker::~QReadLocker() | - | ||||||||||||||||||||||||
| 680 | - | |||||||||||||||||||||||||
| 681 | Destroys the QReadLocker and unlocks the lock that was passed to | - | ||||||||||||||||||||||||
| 682 | the constructor. | - | ||||||||||||||||||||||||
| 683 | - | |||||||||||||||||||||||||
| 684 | \sa QReadWriteLock::unlock() | - | ||||||||||||||||||||||||
| 685 | */ | - | ||||||||||||||||||||||||
| 686 | - | |||||||||||||||||||||||||
| 687 | /*! | - | ||||||||||||||||||||||||
| 688 | \fn void QReadLocker::unlock() | - | ||||||||||||||||||||||||
| 689 | - | |||||||||||||||||||||||||
| 690 | Unlocks the lock associated with this locker. | - | ||||||||||||||||||||||||
| 691 | - | |||||||||||||||||||||||||
| 692 | \sa QReadWriteLock::unlock() | - | ||||||||||||||||||||||||
| 693 | */ | - | ||||||||||||||||||||||||
| 694 | - | |||||||||||||||||||||||||
| 695 | /*! | - | ||||||||||||||||||||||||
| 696 | \fn void QReadLocker::relock() | - | ||||||||||||||||||||||||
| 697 | - | |||||||||||||||||||||||||
| 698 | Relocks an unlocked lock. | - | ||||||||||||||||||||||||
| 699 | - | |||||||||||||||||||||||||
| 700 | \sa unlock() | - | ||||||||||||||||||||||||
| 701 | */ | - | ||||||||||||||||||||||||
| 702 | - | |||||||||||||||||||||||||
| 703 | /*! | - | ||||||||||||||||||||||||
| 704 | \fn QReadWriteLock *QReadLocker::readWriteLock() const | - | ||||||||||||||||||||||||
| 705 | - | |||||||||||||||||||||||||
| 706 | Returns a pointer to the read-write lock that was passed | - | ||||||||||||||||||||||||
| 707 | to the constructor. | - | ||||||||||||||||||||||||
| 708 | */ | - | ||||||||||||||||||||||||
| 709 | - | |||||||||||||||||||||||||
| 710 | /*! | - | ||||||||||||||||||||||||
| 711 | \class QWriteLocker | - | ||||||||||||||||||||||||
| 712 | \inmodule QtCore | - | ||||||||||||||||||||||||
| 713 | \brief The QWriteLocker class is a convenience class that | - | ||||||||||||||||||||||||
| 714 | simplifies locking and unlocking read-write locks for write access. | - | ||||||||||||||||||||||||
| 715 | - | |||||||||||||||||||||||||
| 716 | \threadsafe | - | ||||||||||||||||||||||||
| 717 | - | |||||||||||||||||||||||||
| 718 | \ingroup thread | - | ||||||||||||||||||||||||
| 719 | - | |||||||||||||||||||||||||
| 720 | The purpose of QWriteLocker (and QReadLocker) is to simplify | - | ||||||||||||||||||||||||
| 721 | QReadWriteLock locking and unlocking. Locking and unlocking | - | ||||||||||||||||||||||||
| 722 | statements or in exception handling code is error-prone and | - | ||||||||||||||||||||||||
| 723 | difficult to debug. QWriteLocker can be used in such situations | - | ||||||||||||||||||||||||
| 724 | to ensure that the state of the lock is always well-defined. | - | ||||||||||||||||||||||||
| 725 | - | |||||||||||||||||||||||||
| 726 | Here's an example that uses QWriteLocker to lock and unlock a | - | ||||||||||||||||||||||||
| 727 | read-write lock for writing: | - | ||||||||||||||||||||||||
| 728 | - | |||||||||||||||||||||||||
| 729 | \snippet code/src_corelib_thread_qreadwritelock.cpp 3 | - | ||||||||||||||||||||||||
| 730 | - | |||||||||||||||||||||||||
| 731 | It is equivalent to the following code: | - | ||||||||||||||||||||||||
| 732 | - | |||||||||||||||||||||||||
| 733 | \snippet code/src_corelib_thread_qreadwritelock.cpp 4 | - | ||||||||||||||||||||||||
| 734 | - | |||||||||||||||||||||||||
| 735 | The QMutexLocker documentation shows examples where the use of a | - | ||||||||||||||||||||||||
| 736 | locker object greatly simplifies programming. | - | ||||||||||||||||||||||||
| 737 | - | |||||||||||||||||||||||||
| 738 | \sa QReadLocker, QReadWriteLock | - | ||||||||||||||||||||||||
| 739 | */ | - | ||||||||||||||||||||||||
| 740 | - | |||||||||||||||||||||||||
| 741 | /*! | - | ||||||||||||||||||||||||
| 742 | \fn QWriteLocker::QWriteLocker(QReadWriteLock *lock) | - | ||||||||||||||||||||||||
| 743 | - | |||||||||||||||||||||||||
| 744 | Constructs a QWriteLocker and locks \a lock for writing. The lock | - | ||||||||||||||||||||||||
| 745 | will be unlocked when the QWriteLocker is destroyed. If \c lock is | - | ||||||||||||||||||||||||
| 746 | zero, QWriteLocker does nothing. | - | ||||||||||||||||||||||||
| 747 | - | |||||||||||||||||||||||||
| 748 | \sa QReadWriteLock::lockForWrite() | - | ||||||||||||||||||||||||
| 749 | */ | - | ||||||||||||||||||||||||
| 750 | - | |||||||||||||||||||||||||
| 751 | /*! | - | ||||||||||||||||||||||||
| 752 | \fn QWriteLocker::~QWriteLocker() | - | ||||||||||||||||||||||||
| 753 | - | |||||||||||||||||||||||||
| 754 | Destroys the QWriteLocker and unlocks the lock that was passed to | - | ||||||||||||||||||||||||
| 755 | the constructor. | - | ||||||||||||||||||||||||
| 756 | - | |||||||||||||||||||||||||
| 757 | \sa QReadWriteLock::unlock() | - | ||||||||||||||||||||||||
| 758 | */ | - | ||||||||||||||||||||||||
| 759 | - | |||||||||||||||||||||||||
| 760 | /*! | - | ||||||||||||||||||||||||
| 761 | \fn void QWriteLocker::unlock() | - | ||||||||||||||||||||||||
| 762 | - | |||||||||||||||||||||||||
| 763 | Unlocks the lock associated with this locker. | - | ||||||||||||||||||||||||
| 764 | - | |||||||||||||||||||||||||
| 765 | \sa QReadWriteLock::unlock() | - | ||||||||||||||||||||||||
| 766 | */ | - | ||||||||||||||||||||||||
| 767 | - | |||||||||||||||||||||||||
| 768 | /*! | - | ||||||||||||||||||||||||
| 769 | \fn void QWriteLocker::relock() | - | ||||||||||||||||||||||||
| 770 | - | |||||||||||||||||||||||||
| 771 | Relocks an unlocked lock. | - | ||||||||||||||||||||||||
| 772 | - | |||||||||||||||||||||||||
| 773 | \sa unlock() | - | ||||||||||||||||||||||||
| 774 | */ | - | ||||||||||||||||||||||||
| 775 | - | |||||||||||||||||||||||||
| 776 | /*! | - | ||||||||||||||||||||||||
| 777 | \fn QReadWriteLock *QWriteLocker::readWriteLock() const | - | ||||||||||||||||||||||||
| 778 | - | |||||||||||||||||||||||||
| 779 | Returns a pointer to the read-write lock that was passed | - | ||||||||||||||||||||||||
| 780 | to the constructor. | - | ||||||||||||||||||||||||
| 781 | */ | - | ||||||||||||||||||||||||
| 782 | - | |||||||||||||||||||||||||
| 783 | QT_END_NAMESPACE | - | ||||||||||||||||||||||||
| 784 | - | |||||||||||||||||||||||||
| 785 | #endif // QT_NO_THREAD | - | ||||||||||||||||||||||||
| Source code | Switch to Preprocessed file |