thread/qsemaphore.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
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 "qsemaphore.h" -
43 -
44#ifndef QT_NO_THREAD -
45#include "qmutex.h" -
46#include "qwaitcondition.h" -
47#include "qelapsedtimer.h" -
48#include "qdatetime.h" -
49 -
50QT_BEGIN_NAMESPACE -
51 -
52/*! -
53 \class QSemaphore -
54 \inmodule QtCore -
55 \brief The QSemaphore class provides a general counting semaphore. -
56 -
57 \threadsafe -
58 -
59 \ingroup thread -
60 -
61 A semaphore is a generalization of a mutex. While a mutex can -
62 only be locked once, it's possible to acquire a semaphore -
63 multiple times. Semaphores are typically used to protect a -
64 certain number of identical resources. -
65 -
66 Semaphores support two fundamental operations, acquire() and -
67 release(): -
68 -
69 \list -
70 \li acquire(\e{n}) tries to acquire \e n resources. If there aren't -
71 that many resources available, the call will block until this -
72 is the case. -
73 \li release(\e{n}) releases \e n resources. -
74 \endlist -
75 -
76 There's also a tryAcquire() function that returns immediately if -
77 it cannot acquire the resources, and an available() function that -
78 returns the number of available resources at any time. -
79 -
80 Example: -
81 -
82 \snippet code/src_corelib_thread_qsemaphore.cpp 0 -
83 -
84 A typical application of semaphores is for controlling access to -
85 a circular buffer shared by a producer thread and a consumer -
86 thread. The \l{threads/semaphores}{Semaphores} example shows how -
87 to use QSemaphore to solve that problem. -
88 -
89 A non-computing example of a semaphore would be dining at a -
90 restaurant. A semaphore is initialized with the number of chairs -
91 in the restaurant. As people arrive, they want a seat. As seats -
92 are filled, available() is decremented. As people leave, the -
93 available() is incremented, allowing more people to enter. If a -
94 party of 10 people want to be seated, but there are only 9 seats, -
95 those 10 people will wait, but a party of 4 people would be -
96 seated (taking the available seats to 5, making the party of 10 -
97 people wait longer). -
98 -
99 \sa QMutex, QWaitCondition, QThread, {Semaphores Example} -
100*/ -
101 -
102class QSemaphorePrivate { -
103public: -
104 inline QSemaphorePrivate(int n) : avail(n) { }
executed: }
Execution Count:2159692
2159692
105 -
106 QMutex mutex; -
107 QWaitCondition cond; -
108 -
109 int avail; -
110}; -
111 -
112/*! -
113 Creates a new semaphore and initializes the number of resources -
114 it guards to \a n (by default, 0). -
115 -
116 \sa release(), available() -
117*/ -
118QSemaphore::QSemaphore(int n) -
119{ -
120 Q_ASSERT_X(n >= 0, "QSemaphore", "parameter 'n' must be non-negative");
executed (the execution status of this line is deduced): qt_noop();
-
121 d = new QSemaphorePrivate(n);
executed (the execution status of this line is deduced): d = new QSemaphorePrivate(n);
-
122}
executed: }
Execution Count:2159692
2159692
123 -
124/*! -
125 Destroys the semaphore. -
126 -
127 \warning Destroying a semaphore that is in use may result in -
128 undefined behavior. -
129*/ -
130QSemaphore::~QSemaphore() -
131{ delete d; }
executed: }
Execution Count:2159676
2159676
132 -
133/*! -
134 Tries to acquire \c n resources guarded by the semaphore. If \a n -
135 > available(), this call will block until enough resources are -
136 available. -
137 -
138 \sa release(), available(), tryAcquire() -
139*/ -
140void QSemaphore::acquire(int n) -
141{ -
142 Q_ASSERT_X(n >= 0, "QSemaphore::acquire", "parameter 'n' must be non-negative");
executed (the execution status of this line is deduced): qt_noop();
-
143 QMutexLocker locker(&d->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&d->mutex);
-
144 while (n > d->avail)
evaluated: n > d->avail
TRUEFALSE
yes
Evaluation Count:2521799
yes
Evaluation Count:4203318
2521799-4203318
145 d->cond.wait(locker.mutex());
executed: d->cond.wait(locker.mutex());
Execution Count:2521799
2521799
146 d->avail -= n;
executed (the execution status of this line is deduced): d->avail -= n;
-
147}
executed: }
Execution Count:4201913
4201913
148 -
149/*! -
150 Releases \a n resources guarded by the semaphore. -
151 -
152 This function can be used to "create" resources as well. For -
153 example: -
154 -
155 \snippet code/src_corelib_thread_qsemaphore.cpp 1 -
156 -
157 \sa acquire(), available() -
158*/ -
159void QSemaphore::release(int n) -
160{ -
161 Q_ASSERT_X(n >= 0, "QSemaphore::release", "parameter 'n' must be non-negative");
executed (the execution status of this line is deduced): qt_noop();
-
162 QMutexLocker locker(&d->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&d->mutex);
-
163 d->avail += n;
executed (the execution status of this line is deduced): d->avail += n;
-
164 d->cond.wakeAll();
executed (the execution status of this line is deduced): d->cond.wakeAll();
-
165}
executed: }
Execution Count:8154081
8154081
166 -
167/*! -
168 Returns the number of resources currently available to the -
169 semaphore. This number can never be negative. -
170 -
171 \sa acquire(), release() -
172*/ -
173int QSemaphore::available() const -
174{ -
175 QMutexLocker locker(&d->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&d->mutex);
-
176 return d->avail;
executed: return d->avail;
Execution Count:82
82
177} -
178 -
179/*! -
180 Tries to acquire \c n resources guarded by the semaphore and -
181 returns true on success. If available() < \a n, this call -
182 immediately returns false without acquiring any resources. -
183 -
184 Example: -
185 -
186 \snippet code/src_corelib_thread_qsemaphore.cpp 2 -
187 -
188 \sa acquire() -
189*/ -
190bool QSemaphore::tryAcquire(int n) -
191{ -
192 Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
executed (the execution status of this line is deduced): qt_noop();
-
193 QMutexLocker locker(&d->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&d->mutex);
-
194 if (n > d->avail)
evaluated: n > d->avail
TRUEFALSE
yes
Evaluation Count:8
yes
Evaluation Count:4
4-8
195 return false;
executed: return false;
Execution Count:8
8
196 d->avail -= n;
executed (the execution status of this line is deduced): d->avail -= n;
-
197 return true;
executed: return true;
Execution Count:4
4
198} -
199 -
200/*! -
201 Tries to acquire \c n resources guarded by the semaphore and -
202 returns true on success. If available() < \a n, this call will -
203 wait for at most \a timeout milliseconds for resources to become -
204 available. -
205 -
206 Note: Passing a negative number as the \a timeout is equivalent to -
207 calling acquire(), i.e. this function will wait forever for -
208 resources to become available if \a timeout is negative. -
209 -
210 Example: -
211 -
212 \snippet code/src_corelib_thread_qsemaphore.cpp 3 -
213 -
214 \sa acquire() -
215*/ -
216bool QSemaphore::tryAcquire(int n, int timeout) -
217{ -
218 Q_ASSERT_X(n >= 0, "QSemaphore::tryAcquire", "parameter 'n' must be non-negative");
executed (the execution status of this line is deduced): qt_noop();
-
219 QMutexLocker locker(&d->mutex);
executed (the execution status of this line is deduced): QMutexLocker locker(&d->mutex);
-
220 if (timeout < 0) {
partially evaluated: timeout < 0
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:3945047
0-3945047
221 while (n > d->avail)
never evaluated: n > d->avail
0
222 d->cond.wait(locker.mutex());
never executed: d->cond.wait(locker.mutex());
0
223 } else {
never executed: }
0
224 QElapsedTimer timer;
executed (the execution status of this line is deduced): QElapsedTimer timer;
-
225 timer.start();
executed (the execution status of this line is deduced): timer.start();
-
226 while (n > d->avail) {
evaluated: n > d->avail
TRUEFALSE
yes
Evaluation Count:221643
yes
Evaluation Count:3945024
221643-3945024
227 const qint64 elapsed = timer.elapsed();
executed (the execution status of this line is deduced): const qint64 elapsed = timer.elapsed();
-
228 if (timeout - elapsed <= 0
evaluated: timeout - elapsed <= 0
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:221642
1-221642
229 || !d->cond.wait(locker.mutex(), timeout - elapsed))
evaluated: !d->cond.wait(locker.mutex(), timeout - elapsed)
TRUEFALSE
yes
Evaluation Count:22
yes
Evaluation Count:221620
22-221620
230 return false;
executed: return false;
Execution Count:23
23
231 }
executed: }
Execution Count:221620
221620
232 }
executed: }
Execution Count:3945024
3945024
233 d->avail -= n;
executed (the execution status of this line is deduced): d->avail -= n;
-
234 return true;
executed: return true;
Execution Count:3945024
3945024
235 -
236 -
237} -
238 -
239QT_END_NAMESPACE -
240 -
241#endif // QT_NO_THREAD -
242 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial