Line | Source Code | Coverage |
---|
1 | /**************************************************************************** | - |
2 | ** | - |
3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). | - |
4 | ** Contact: http://www.qt-project.org/legal | - |
5 | ** | - |
6 | ** This file is part of the QtCore module of the Qt Toolkit. | - |
7 | ** | - |
8 | ** $QT_BEGIN_LICENSE:LGPL$ | - |
9 | ** Commercial License Usage | - |
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - |
11 | ** accordance with the commercial license agreement provided with the | - |
12 | ** Software or, alternatively, in accordance with the terms contained in | - |
13 | ** a written agreement between you and Digia. For licensing terms and | - |
14 | ** conditions see http://qt.digia.com/licensing. For further information | - |
15 | ** use the contact form at http://qt.digia.com/contact-us. | - |
16 | ** | - |
17 | ** GNU Lesser General Public License Usage | - |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - |
19 | ** General Public License version 2.1 as published by the Free Software | - |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the | - |
21 | ** packaging of this file. Please review the following information to | - |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements | - |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | - |
24 | ** | - |
25 | ** In addition, as a special exception, Digia gives you certain additional | - |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception | - |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | - |
28 | ** | - |
29 | ** GNU General Public License Usage | - |
30 | ** Alternatively, this file may be used under the terms of the GNU | - |
31 | ** General Public License version 3.0 as published by the Free Software | - |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the | - |
33 | ** packaging of this file. Please review the following information to | - |
34 | ** ensure the GNU General Public License version 3.0 requirements will be | - |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. | - |
36 | ** | - |
37 | ** | - |
38 | ** $QT_END_LICENSE$ | - |
39 | ** | - |
40 | ****************************************************************************/ | - |
41 | | - |
42 | #include "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 | | - |
50 | QT_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 | | - |
102 | class QSemaphorePrivate { | - |
103 | public: | - |
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 | */ | - |
118 | QSemaphore::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 | */ | - |
130 | QSemaphore::~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 | */ | - |
140 | void 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 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 | */ | - |
159 | void 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 | */ | - |
173 | int 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 | */ | - |
190 | bool 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 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 | */ | - |
216 | bool 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 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 { | 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 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 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) 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 | | - |
239 | QT_END_NAMESPACE | - |
240 | | - |
241 | #endif // QT_NO_THREAD | - |
242 | | - |
| | |