thread/qmutex.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Copyright (C) 2012 Intel Corporation -
5** Copyright (C) 2012 Olivier Goffart <ogoffart@woboq.com> -
6** Contact: http://www.qt-project.org/legal -
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 Digia. For licensing terms and -
16** conditions see http://qt.digia.com/licensing. For further information -
17** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software -
22** Foundation and appearing in the file LICENSE.LGPL included in the -
23** packaging of this file. Please review the following information to -
24** ensure the GNU Lesser General Public License version 2.1 requirements -
25** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
26** -
27** In addition, as a special exception, Digia gives you certain additional -
28** rights. These rights are described in the Digia Qt LGPL Exception -
29** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
30** -
31** GNU General Public License Usage -
32** Alternatively, this file may be used under the terms of the GNU -
33** General Public License version 3.0 as published by the Free Software -
34** Foundation and appearing in the file LICENSE.GPL included in the -
35** packaging of this file. Please review the following information to -
36** ensure the GNU General Public License version 3.0 requirements will be -
37** met: http://www.gnu.org/copyleft/gpl.html. -
38** -
39** -
40** $QT_END_LICENSE$ -
41** -
42****************************************************************************/ -
43 -
44#include "qplatformdefs.h" -
45#include "qmutex.h" -
46#include <qdebug.h> -
47 -
48#ifndef QT_NO_THREAD -
49#include "qatomic.h" -
50#include "qelapsedtimer.h" -
51#include "qthread.h" -
52#include "qmutex_p.h" -
53 -
54#ifndef QT_LINUX_FUTEX -
55#include "private/qfreelist_p.h" -
56#endif -
57 -
58QT_BEGIN_NAMESPACE -
59 -
60static inline bool isRecursive(QMutexData *d) -
61{ -
62 register quintptr u = quintptr(d);
executed (the execution status of this line is deduced): register quintptr u = quintptr(d);
-
63 if (Q_LIKELY(u <= 0x3))
evaluated: __builtin_expect(!!(u <= 0x3), true)
TRUEFALSE
yes
Evaluation Count:28807206
yes
Evaluation Count:2150349
2150349-28807206
64 return false;
executed: return false;
Execution Count:28817391
28817391
65#ifdef QT_LINUX_FUTEX -
66 Q_ASSERT(d->recursive);
executed (the execution status of this line is deduced): qt_noop();
-
67 return true;
executed: return true;
Execution Count:2150356
2150356
68#else -
69 return d->recursive; -
70#endif -
71} -
72 -
73class QRecursiveMutexPrivate : public QMutexData -
74{ -
75public: -
76 QRecursiveMutexPrivate() -
77 : QMutexData(QMutex::Recursive), owner(0), count(0) {}
executed: }
Execution Count:2832
2832
78 Qt::HANDLE owner; -
79 uint count; -
80 QMutex mutex; -
81 -
82 bool lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT; -
83 void unlock() Q_DECL_NOTHROW; -
84}; -
85 -
86/* -
87 \class QBasicMutex -
88 \inmodule QtCore -
89 \brief QMutex POD -
90 \internal -
91 -
92 \ingroup thread -
93 -
94 - Can be used as global static object. -
95 - Always non-recursive -
96 - Do not use tryLock with timeout > 0, else you can have a leak (see the ~QMutex destructor) -
97*/ -
98 -
99/*! -
100 \class QMutex -
101 \inmodule QtCore -
102 \brief The QMutex class provides access serialization between threads. -
103 -
104 \threadsafe -
105 -
106 \ingroup thread -
107 -
108 The purpose of a QMutex is to protect an object, data structure or -
109 section of code so that only one thread can access it at a time -
110 (this is similar to the Java \c synchronized keyword). It is -
111 usually best to use a mutex with a QMutexLocker since this makes -
112 it easy to ensure that locking and unlocking are performed -
113 consistently. -
114 -
115 For example, say there is a method that prints a message to the -
116 user on two lines: -
117 -
118 \snippet code/src_corelib_thread_qmutex.cpp 0 -
119 -
120 If these two methods are called in succession, the following happens: -
121 -
122 \snippet code/src_corelib_thread_qmutex.cpp 1 -
123 -
124 If these two methods are called simultaneously from two threads then the -
125 following sequence could result: -
126 -
127 \snippet code/src_corelib_thread_qmutex.cpp 2 -
128 -
129 If we add a mutex, we should get the result we want: -
130 -
131 \snippet code/src_corelib_thread_qmutex.cpp 3 -
132 -
133 Then only one thread can modify \c number at any given time and -
134 the result is correct. This is a trivial example, of course, but -
135 applies to any other case where things need to happen in a -
136 particular sequence. -
137 -
138 When you call lock() in a thread, other threads that try to call -
139 lock() in the same place will block until the thread that got the -
140 lock calls unlock(). A non-blocking alternative to lock() is -
141 tryLock(). -
142 -
143 \sa QMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition -
144*/ -
145 -
146/*! -
147 \enum QMutex::RecursionMode -
148 -
149 \value Recursive In this mode, a thread can lock the same mutex -
150 multiple times and the mutex won't be unlocked -
151 until a corresponding number of unlock() calls -
152 have been made. -
153 -
154 \value NonRecursive In this mode, a thread may only lock a mutex -
155 once. -
156 -
157 \sa QMutex() -
158*/ -
159 -
160/*! -
161 Constructs a new mutex. The mutex is created in an unlocked state. -
162 -
163 If \a mode is QMutex::Recursive, a thread can lock the same mutex -
164 multiple times and the mutex won't be unlocked until a -
165 corresponding number of unlock() calls have been made. Otherwise -
166 a thread may only lock a mutex once. The default is -
167 QMutex::NonRecursive. -
168 -
169 \sa lock(), unlock() -
170*/ -
171QMutex::QMutex(RecursionMode mode) -
172{ -
173 d_ptr.store(mode == Recursive ? new QRecursiveMutexPrivate : 0);
executed (the execution status of this line is deduced): d_ptr.store(mode == Recursive ? new QRecursiveMutexPrivate : 0);
-
174}
executed: }
Execution Count:6100234
6100234
175 -
176/*! -
177 Destroys the mutex. -
178 -
179 \warning Destroying a locked mutex may result in undefined behavior. -
180*/ -
181QMutex::~QMutex() -
182{ -
183 QMutexData *d = d_ptr.load();
executed (the execution status of this line is deduced): QMutexData *d = d_ptr.load();
-
184 if (isRecursive()) {
evaluated: isRecursive()
TRUEFALSE
yes
Evaluation Count:3976
yes
Evaluation Count:6099918
3976-6099918
185 delete static_cast<QRecursiveMutexPrivate *>(d);
executed (the execution status of this line is deduced): delete static_cast<QRecursiveMutexPrivate *>(d);
-
186 } else if (d) {
executed: }
Execution Count:3976
evaluated: d
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:6099293
1-6099293
187#ifndef QT_LINUX_FUTEX -
188 if (d != dummyLocked() && static_cast<QMutexPrivate *>(d)->possiblyUnlocked.load() -
189 && tryLock()) { -
190 unlock(); -
191 return; -
192 } -
193#endif -
194 qWarning("QMutex: destroying locked mutex");
executed (the execution status of this line is deduced): QMessageLogger("thread/qmutex.cpp", 194, __PRETTY_FUNCTION__).warning("QMutex: destroying locked mutex");
-
195 }
executed: }
Execution Count:1
1
196} -
197 -
198/*! \fn void QMutex::lock() -
199 Locks the mutex. If another thread has locked the mutex then this -
200 call will block until that thread has unlocked it. -
201 -
202 Calling this function multiple times on the same mutex from the -
203 same thread is allowed if this mutex is a -
204 \l{QMutex::Recursive}{recursive mutex}. If this mutex is a -
205 \l{QMutex::NonRecursive}{non-recursive mutex}, this function will -
206 \e dead-lock when the mutex is locked recursively. -
207 -
208 \sa unlock() -
209*/ -
210void QMutex::lock() QT_MUTEX_LOCK_NOEXCEPT -
211{ -
212 if (fastTryLock())
evaluated: fastTryLock()
TRUEFALSE
yes
Evaluation Count:83041693
yes
Evaluation Count:5693977
5693977-83041693
213 return;
executed: return;
Execution Count:83027132
83027132
214 QMutexData *current = d_ptr.loadAcquire();
executed (the execution status of this line is deduced): QMutexData *current = d_ptr.loadAcquire();
-
215 if (QT_PREPEND_NAMESPACE(isRecursive)(current))
evaluated: ::isRecursive(current)
TRUEFALSE
yes
Evaluation Count:1067383
yes
Evaluation Count:4623445
1067383-4623445
216 static_cast<QRecursiveMutexPrivate *>(current)->lock(-1);
executed: static_cast<QRecursiveMutexPrivate *>(current)->lock(-1);
Execution Count:1067379
1067379
217 else -
218 lockInternal();
executed: lockInternal();
Execution Count:4621810
4621810
219} -
220 -
221/*! \fn bool QMutex::tryLock(int timeout) -
222 -
223 Attempts to lock the mutex. This function returns true if the lock -
224 was obtained; otherwise it returns false. If another thread has -
225 locked the mutex, this function will wait for at most \a timeout -
226 milliseconds for the mutex to become available. -
227 -
228 Note: Passing a negative number as the \a timeout is equivalent to -
229 calling lock(), i.e. this function will wait forever until mutex -
230 can be locked if \a timeout is negative. -
231 -
232 If the lock was obtained, the mutex must be unlocked with unlock() -
233 before another thread can successfully lock it. -
234 -
235 Calling this function multiple times on the same mutex from the -
236 same thread is allowed if this mutex is a -
237 \l{QMutex::Recursive}{recursive mutex}. If this mutex is a -
238 \l{QMutex::NonRecursive}{non-recursive mutex}, this function will -
239 \e always return false when attempting to lock the mutex -
240 recursively. -
241 -
242 \sa lock(), unlock() -
243*/ -
244bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT -
245{ -
246 if (fastTryLock())
evaluated: fastTryLock()
TRUEFALSE
yes
Evaluation Count:5267752
yes
Evaluation Count:257876
257876-5267752
247 return true;
executed: return true;
Execution Count:5267751
5267751
248 QMutexData *current = d_ptr.loadAcquire();
executed (the execution status of this line is deduced): QMutexData *current = d_ptr.loadAcquire();
-
249 if (QT_PREPEND_NAMESPACE(isRecursive)(current))
evaluated: ::isRecursive(current)
TRUEFALSE
yes
Evaluation Count:10819
yes
Evaluation Count:243072
10819-243072
250 return static_cast<QRecursiveMutexPrivate *>(current)->lock(timeout);
executed: return static_cast<QRecursiveMutexPrivate *>(current)->lock(timeout);
Execution Count:10819
10819
251 else -
252 return lockInternal(timeout);
executed: return lockInternal(timeout);
Execution Count:241421
241421
253} -
254 -
255/*! \fn void QMutex::unlock() -
256 Unlocks the mutex. Attempting to unlock a mutex in a different -
257 thread to the one that locked it results in an error. Unlocking a -
258 mutex that is not locked results in undefined behavior. -
259 -
260 \sa lock() -
261*/ -
262void QMutex::unlock() Q_DECL_NOTHROW -
263{ -
264 if (fastTryUnlock())
evaluated: fastTryUnlock()
TRUEFALSE
yes
Evaluation Count:85094430
yes
Evaluation Count:8946247
8946247-85094430
265 return;
executed: return;
Execution Count:85079807
85079807
266 QMutexData *current = d_ptr.loadAcquire();
executed (the execution status of this line is deduced): QMutexData *current = d_ptr.loadAcquire();
-
267 if (QT_PREPEND_NAMESPACE(isRecursive)(current))
evaluated: ::isRecursive(current)
TRUEFALSE
yes
Evaluation Count:1068201
yes
Evaluation Count:7877992
1068201-7877992
268 static_cast<QRecursiveMutexPrivate *>(current)->unlock();
executed: static_cast<QRecursiveMutexPrivate *>(current)->unlock();
Execution Count:1068201
1068201
269 else -
270 unlockInternal();
executed: unlockInternal();
Execution Count:7877982
7877982
271} -
272 -
273/*! -
274 \fn void QMutex::isRecursive() -
275 \since 5.0 -
276 -
277 Returns true if the mutex is recursive -
278 -
279*/ -
280bool QBasicMutex::isRecursive() -
281{ -
282 return QT_PREPEND_NAMESPACE(isRecursive)(d_ptr.loadAcquire());
executed: return ::isRecursive(d_ptr.loadAcquire());
Execution Count:16169411
16169411
283} -
284 -
285 -
286/*! -
287 \class QMutexLocker -
288 \inmodule QtCore -
289 \brief The QMutexLocker class is a convenience class that simplifies -
290 locking and unlocking mutexes. -
291 -
292 \threadsafe -
293 -
294 \ingroup thread -
295 -
296 Locking and unlocking a QMutex in complex functions and -
297 statements or in exception handling code is error-prone and -
298 difficult to debug. QMutexLocker can be used in such situations -
299 to ensure that the state of the mutex is always well-defined. -
300 -
301 QMutexLocker should be created within a function where a -
302 QMutex needs to be locked. The mutex is locked when QMutexLocker -
303 is created. You can unlock and relock the mutex with \c unlock() -
304 and \c relock(). If locked, the mutex will be unlocked when the -
305 QMutexLocker is destroyed. -
306 -
307 For example, this complex function locks a QMutex upon entering -
308 the function and unlocks the mutex at all the exit points: -
309 -
310 \snippet code/src_corelib_thread_qmutex.cpp 4 -
311 -
312 This example function will get more complicated as it is -
313 developed, which increases the likelihood that errors will occur. -
314 -
315 Using QMutexLocker greatly simplifies the code, and makes it more -
316 readable: -
317 -
318 \snippet code/src_corelib_thread_qmutex.cpp 5 -
319 -
320 Now, the mutex will always be unlocked when the QMutexLocker -
321 object is destroyed (when the function returns since \c locker is -
322 an auto variable). -
323 -
324 The same principle applies to code that throws and catches -
325 exceptions. An exception that is not caught in the function that -
326 has locked the mutex has no way of unlocking the mutex before the -
327 exception is passed up the stack to the calling function. -
328 -
329 QMutexLocker also provides a \c mutex() member function that returns -
330 the mutex on which the QMutexLocker is operating. This is useful -
331 for code that needs access to the mutex, such as -
332 QWaitCondition::wait(). For example: -
333 -
334 \snippet code/src_corelib_thread_qmutex.cpp 6 -
335 -
336 \sa QReadLocker, QWriteLocker, QMutex -
337*/ -
338 -
339/*! -
340 \fn QMutexLocker::QMutexLocker(QMutex *mutex) -
341 -
342 Constructs a QMutexLocker and locks \a mutex. The mutex will be -
343 unlocked when the QMutexLocker is destroyed. If \a mutex is zero, -
344 QMutexLocker does nothing. -
345 -
346 \sa QMutex::lock() -
347*/ -
348 -
349/*! -
350 \fn QMutexLocker::~QMutexLocker() -
351 -
352 Destroys the QMutexLocker and unlocks the mutex that was locked -
353 in the constructor. -
354 -
355 \sa QMutex::unlock() -
356*/ -
357 -
358/*! -
359 \fn void QMutexLocker::unlock() -
360 -
361 Unlocks this mutex locker. You can use \c relock() to lock -
362 it again. It does not need to be locked when destroyed. -
363 -
364 \sa relock() -
365*/ -
366 -
367/*! -
368 \fn void QMutexLocker::relock() -
369 -
370 Relocks an unlocked mutex locker. -
371 -
372 \sa unlock() -
373*/ -
374 -
375/*! -
376 \fn QMutex *QMutexLocker::mutex() -
377 -
378 Returns the mutex on which the QMutexLocker is operating. -
379 -
380*/ -
381 -
382#ifndef QT_LINUX_FUTEX //linux implementation is in qmutex_linux.cpp -
383 -
384/* -
385 For a rough introduction on how this works, refer to -
386 http://woboq.com/blog/internals-of-qmutex-in-qt5.html -
387 which explains a slightly simplified version of it. -
388 The differences are that here we try to work with timeout (requires the -
389 possiblyUnlocked flag) and that we only wake one thread when unlocking -
390 (requires maintaining the waiters count) -
391 We also support recursive mutexes which always have a valid d_ptr. -
392 -
393 The waiters flag represents the number of threads that are waiting or about -
394 to wait on the mutex. There are two tricks to keep in mind: -
395 We don't want to increment waiters after we checked no threads are waiting -
396 (waiters == 0). That's why we atomically set the BigNumber flag on waiters when -
397 we check waiters. Similarly, if waiters is decremented right after we checked, -
398 the mutex would be unlocked (d->wakeUp() has (or will) be called), but there is -
399 no thread waiting. This is only happening if there was a timeout in tryLock at the -
400 same time as the mutex is unlocked. So when there was a timeout, we set the -
401 possiblyUnlocked flag. -
402*/ -
403 -
404/*! -
405 \internal helper for lock() -
406 */ -
407void QBasicMutex::lockInternal() QT_MUTEX_LOCK_NOEXCEPT -
408{ -
409 lockInternal(-1); -
410} -
411 -
412/*! -
413 \internal helper for lock(int) -
414 */ -
415bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT -
416{ -
417 Q_ASSERT(!isRecursive()); -
418 -
419 while (!fastTryLock()) { -
420 QMutexData *copy = d_ptr.loadAcquire(); -
421 if (!copy) // if d is 0, the mutex is unlocked -
422 continue; -
423 -
424 if (copy == dummyLocked()) { -
425 if (timeout == 0) -
426 return false; -
427 // The mutex is locked but does not have a QMutexPrivate yet. -
428 // we need to allocate a QMutexPrivate -
429 QMutexPrivate *newD = QMutexPrivate::allocate(); -
430 if (!d_ptr.testAndSetOrdered(dummyLocked(), newD)) { -
431 //Either the mutex is already unlocked, or another thread already set it. -
432 newD->deref(); -
433 continue; -
434 } -
435 copy = newD; -
436 //the d->refCount is already 1 the deref will occurs when we unlock -
437 } -
438 -
439 QMutexPrivate *d = static_cast<QMutexPrivate *>(copy); -
440 if (timeout == 0 && !d->possiblyUnlocked.load()) -
441 return false; -
442 -
443 // At this point we have a pointer to a QMutexPrivate. But the other thread -
444 // may unlock the mutex at any moment and release the QMutexPrivate to the pool. -
445 // We will try to reference it to avoid unlock to release it to the pool to make -
446 // sure it won't be released. But if the refcount is already 0 it has been released. -
447 if (!d->ref()) -
448 continue; //that QMutexData was already released -
449 -
450 // We now hold a reference to the QMutexPrivate. It won't be released and re-used. -
451 // But it is still possible that it was already re-used by another QMutex right before -
452 // we did the ref(). So check if we still hold a pointer to the right mutex. -
453 if (d != d_ptr.loadAcquire()) { -
454 //Either the mutex is already unlocked, or relocked with another mutex -
455 d->deref(); -
456 continue; -
457 } -
458 -
459 // In this part, we will try to increment the waiters count. -
460 // We just need to take care of the case in which the old_waiters -
461 // is set to the BigNumber magic value set in unlockInternal() -
462 int old_waiters; -
463 do { -
464 old_waiters = d->waiters.load(); -
465 if (old_waiters == -QMutexPrivate::BigNumber) { -
466 // we are unlocking, and the thread that unlocks is about to change d to 0 -
467 // we try to acquire the mutex by changing to dummyLocked() -
468 if (d_ptr.testAndSetAcquire(d, dummyLocked())) { -
469 // Mutex acquired -
470 Q_ASSERT(d->waiters.load() == -QMutexPrivate::BigNumber || d->waiters.load() == 0); -
471 d->waiters.store(0); -
472 d->deref(); -
473 return true; -
474 } else { -
475 Q_ASSERT(d != d_ptr.load()); //else testAndSetAcquire should have succeeded -
476 // Mutex is likely to bo 0, we should continue the outer-loop, -
477 // set old_waiters to the magic value of BigNumber -
478 old_waiters = QMutexPrivate::BigNumber; -
479 break; -
480 } -
481 } -
482 } while (!d->waiters.testAndSetRelaxed(old_waiters, old_waiters + 1)); -
483 -
484 if (d != d_ptr.loadAcquire()) { -
485 // The mutex was unlocked before we incremented waiters. -
486 if (old_waiters != QMutexPrivate::BigNumber) { -
487 //we did not break the previous loop -
488 Q_ASSERT(d->waiters.load() >= 1); -
489 d->waiters.deref(); -
490 } -
491 d->deref(); -
492 continue; -
493 } -
494 -
495 if (d->wait(timeout)) { -
496 // reset the possiblyUnlocked flag if needed (and deref its corresponding reference) -
497 if (d->possiblyUnlocked.load() && d->possiblyUnlocked.testAndSetRelaxed(true, false)) -
498 d->deref(); -
499 d->derefWaiters(1); -
500 //we got the lock. (do not deref) -
501 Q_ASSERT(d == d_ptr.load()); -
502 return true; -
503 } else { -
504 Q_ASSERT(timeout >= 0); -
505 //timeout -
506 d->derefWaiters(1); -
507 //There may be a race in which the mutex is unlocked right after we timed out, -
508 // and before we deref the waiters, so maybe the mutex is actually unlocked. -
509 // Set the possiblyUnlocked flag to indicate this possibility. -
510 if (!d->possiblyUnlocked.testAndSetRelaxed(false, true)) { -
511 // We keep a reference when possiblyUnlocked is true. -
512 // but if possiblyUnlocked was already true, we don't need to keep the reference. -
513 d->deref(); -
514 } -
515 return false; -
516 } -
517 } -
518 Q_ASSERT(d_ptr.load() != 0); -
519 return true; -
520} -
521 -
522/*! -
523 \internal -
524*/ -
525void QBasicMutex::unlockInternal() Q_DECL_NOTHROW -
526{ -
527 QMutexData *copy = d_ptr.loadAcquire(); -
528 Q_ASSERT(copy); //we must be locked -
529 Q_ASSERT(copy != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed -
530 Q_ASSERT(!isRecursive()); -
531 -
532 QMutexPrivate *d = reinterpret_cast<QMutexPrivate *>(copy); -
533 -
534 // If no one is waiting for the lock anymore, we should reset d to 0x0. -
535 // Using fetchAndAdd, we atomically check that waiters was equal to 0, and add a flag -
536 // to the waiters variable (BigNumber). That way, we avoid the race in which waiters is -
537 // incremented right after we checked, because we won't increment waiters if is -
538 // equal to -BigNumber -
539 if (d->waiters.fetchAndAddRelease(-QMutexPrivate::BigNumber) == 0) { -
540 //there is no one waiting on this mutex anymore, set the mutex as unlocked (d = 0) -
541 if (d_ptr.testAndSetRelease(d, 0)) { -
542 // reset the possiblyUnlocked flag if needed (and deref its corresponding reference) -
543 if (d->possiblyUnlocked.load() && d->possiblyUnlocked.testAndSetRelaxed(true, false)) -
544 d->deref(); -
545 } -
546 d->derefWaiters(0); -
547 } else { -
548 d->derefWaiters(0); -
549 //there are thread waiting, transfer the lock. -
550 d->wakeUp(); -
551 } -
552 d->deref(); -
553} -
554 -
555//The freelist management -
556namespace { -
557struct FreeListConstants : QFreeListDefaultConstants { -
558 enum { BlockCount = 4, MaxIndex=0xffff }; -
559 static const int Sizes[BlockCount]; -
560}; -
561const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = { -
562 16, -
563 128, -
564 1024, -
565 FreeListConstants::MaxIndex - (16-128-1024) -
566}; -
567 -
568typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList; -
569Q_GLOBAL_STATIC(FreeList, freelist); -
570} -
571 -
572QMutexPrivate *QMutexPrivate::allocate() -
573{ -
574 int i = freelist()->next(); -
575 QMutexPrivate *d = &(*freelist())[i]; -
576 d->id = i; -
577 Q_ASSERT(d->refCount.load() == 0); -
578 Q_ASSERT(!d->recursive); -
579 Q_ASSERT(!d->possiblyUnlocked.load()); -
580 Q_ASSERT(d->waiters.load() == 0); -
581 d->refCount.store(1); -
582 return d; -
583} -
584 -
585void QMutexPrivate::release() -
586{ -
587 Q_ASSERT(!recursive); -
588 Q_ASSERT(refCount.load() == 0); -
589 Q_ASSERT(!possiblyUnlocked.load()); -
590 Q_ASSERT(waiters.load() == 0); -
591 freelist()->release(id); -
592} -
593 -
594// atomically subtract "value" to the waiters, and remove the QMutexPrivate::BigNumber flag -
595void QMutexPrivate::derefWaiters(int value) Q_DECL_NOTHROW -
596{ -
597 int old_waiters; -
598 int new_waiters; -
599 do { -
600 old_waiters = waiters.load(); -
601 new_waiters = old_waiters; -
602 if (new_waiters < 0) { -
603 new_waiters += QMutexPrivate::BigNumber; -
604 } -
605 new_waiters -= value; -
606 } while (!waiters.testAndSetRelaxed(old_waiters, new_waiters)); -
607} -
608#endif -
609 -
610/*! -
611 \internal -
612 */ -
613inline bool QRecursiveMutexPrivate::lock(int timeout) QT_MUTEX_LOCK_NOEXCEPT -
614{ -
615 Qt::HANDLE self = QThread::currentThreadId();
executed (the execution status of this line is deduced): Qt::HANDLE self = QThread::currentThreadId();
-
616 if (owner == self) {
evaluated: owner == self
TRUEFALSE
yes
Evaluation Count:2240
yes
Evaluation Count:1075954
2240-1075954
617 ++count;
executed (the execution status of this line is deduced): ++count;
-
618 Q_ASSERT_X(count != 0, "QMutex::lock", "Overflow in recursion counter");
executed (the execution status of this line is deduced): qt_noop();
-
619 return true;
executed: return true;
Execution Count:2240
2240
620 } -
621 bool success = true;
executed (the execution status of this line is deduced): bool success = true;
-
622 if (timeout == -1) {
evaluated: timeout == -1
TRUEFALSE
yes
Evaluation Count:1065742
yes
Evaluation Count:10216
10216-1065742
623 mutex.QBasicMutex::lock();
executed (the execution status of this line is deduced): mutex.QBasicMutex::lock();
-
624 } else {
executed: }
Execution Count:1065759
1065759
625 success = mutex.tryLock(timeout);
executed (the execution status of this line is deduced): success = mutex.tryLock(timeout);
-
626 }
executed: }
Execution Count:10216
10216
627 -
628 if (success)
evaluated: success
TRUEFALSE
yes
Evaluation Count:1065966
yes
Evaluation Count:10008
10008-1065966
629 owner = self;
executed: owner = self;
Execution Count:1065942
1065942
630 return success;
executed: return success;
Execution Count:1075972
1075972
631} -
632 -
633/*! -
634 \internal -
635 */ -
636inline void QRecursiveMutexPrivate::unlock() Q_DECL_NOTHROW -
637{ -
638 if (count > 0) {
evaluated: count > 0
TRUEFALSE
yes
Evaluation Count:2240
yes
Evaluation Count:1065953
2240-1065953
639 count--;
executed (the execution status of this line is deduced): count--;
-
640 } else {
executed: }
Execution Count:2240
2240
641 owner = 0;
executed (the execution status of this line is deduced): owner = 0;
-
642 mutex.QBasicMutex::unlock();
executed (the execution status of this line is deduced): mutex.QBasicMutex::unlock();
-
643 }
executed: }
Execution Count:1065967
1065967
644} -
645 -
646QT_END_NAMESPACE -
647 -
648#ifdef QT_LINUX_FUTEX -
649# include "qmutex_linux.cpp" -
650#elif defined(Q_OS_MAC) -
651# include "qmutex_mac.cpp" -
652#elif defined(Q_OS_WIN) -
653# include "qmutex_win.cpp" -
654#else -
655# include "qmutex_unix.cpp" -
656#endif -
657 -
658#endif // QT_NO_THREAD -
659 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial