summaryrefslogtreecommitdiff
path: root/qmake/tools/qsemaphore_unix.cpp
Unidiff
Diffstat (limited to 'qmake/tools/qsemaphore_unix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--qmake/tools/qsemaphore_unix.cpp292
1 files changed, 292 insertions, 0 deletions
diff --git a/qmake/tools/qsemaphore_unix.cpp b/qmake/tools/qsemaphore_unix.cpp
new file mode 100644
index 0000000..fcf28da
--- a/dev/null
+++ b/qmake/tools/qsemaphore_unix.cpp
@@ -0,0 +1,292 @@
1/****************************************************************************
2** $Id$
3**
4** QSemaphore class for Unix
5**
6** Created : 20010725
7**
8** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
9**
10** This file is part of the tools module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#if defined(QT_THREAD_SUPPORT)
39
40#include "qsemaphore.h"
41#include "qmutex.h"
42#include "qwaitcondition.h"
43
44
45/*!
46 \class QSemaphore qsemaphore.h
47 \threadsafe
48 \brief The QSemaphore class provides a robust integer semaphore.
49
50 \ingroup thread
51 \ingroup environment
52
53 A QSemaphore can be used to serialize thread execution, in a
54 similar way to a QMutex. A semaphore differs from a mutex, in
55 that a semaphore can be accessed by more than one thread at a
56 time.
57
58 For example, suppose we have an application that stores data in a
59 large tree structure. The application creates 10 threads
60 (commonly called a thread pool) to perform searches on the tree.
61 When the application searches the tree for some piece of data, it
62 uses one thread per base node to do the searching. A semaphore
63 could be used to make sure that two threads don't try to search
64 the same branch of the tree at the same time.
65
66 A non-computing example of a semaphore would be dining at a
67 restuarant. A semaphore is initialized to have a maximum count
68 equal to the number of chairs in the restuarant. As people
69 arrive, they want a seat. As seats are filled, the semaphore is
70 accessed, once per person. As people leave, the access is
71 released, allowing more people to enter. If a party of 10 people
72 want to be seated, but there are only 9 seats, those 10 people
73 will wait, but a party of 4 people would be seated (taking the
74 available seats to 5, making the party of 10 people wait longer).
75
76 When a semaphore is created it is given a number which is the
77 maximum number of concurrent accesses it will permit. This amount
78 may be changed using operator++(), operator--(), operator+=() and
79 operator-=(). The number of accesses allowed is retrieved with
80 available(), and the total number with total(). Note that the
81 incrementing functions will block if there aren't enough available
82 accesses. Use tryAccess() if you want to acquire accesses without
83 blocking.
84*/
85
86
87class QSemaphorePrivate {
88public:
89 QSemaphorePrivate(int);
90
91 QMutex mutex;
92 QWaitCondition cond;
93
94 int value, max;
95};
96
97
98QSemaphorePrivate::QSemaphorePrivate(int m)
99 : mutex(FALSE), value(0), max(m)
100{
101}
102
103
104/*!
105 Creates a new semaphore. The semaphore can be concurrently
106 accessed at most \a maxcount times.
107*/
108QSemaphore::QSemaphore(int maxcount)
109{
110 d = new QSemaphorePrivate(maxcount);
111}
112
113
114/*!
115 Destroys the semaphore.
116
117 \warning If you destroy a semaphore that has accesses in use the
118 resultant behavior is undefined.
119*/
120QSemaphore::~QSemaphore()
121{
122 delete d;
123}
124
125
126/*!
127 Postfix ++ operator.
128
129 Try to get access to the semaphore. If \l available() == 0, this
130 call will block until it can get access, i.e. until available() \>
131 0.
132*/
133int QSemaphore::operator++(int)
134{
135 int ret;
136
137 d->mutex.lock();
138
139 while (d->value >= d->max)
140 d->cond.wait(&(d->mutex));
141
142 ++(d->value);
143 if (d->value > d->max) d->value = d->max;
144 ret = d->value;
145
146 d->mutex.unlock();
147
148 return ret;
149}
150
151
152/*!
153 Postfix -- operator.
154
155 Release access of the semaphore. This wakes all threads waiting
156 for access to the semaphore.
157*/
158int QSemaphore::operator--(int)
159{
160 int ret;
161
162 d->mutex.lock();
163
164 --(d->value);
165 if (d->value < 0) d->value = 0;
166 ret = d->value;
167
168 d->cond.wakeAll();
169 d->mutex.unlock();
170
171 return ret;
172}
173
174
175/*!
176 Try to get access to the semaphore. If \l available() \< \a n, this
177 call will block until it can get all the accesses it wants, i.e.
178 until available() \>= \a n.
179*/
180int QSemaphore::operator+=(int n)
181{
182 int ret;
183
184 d->mutex.lock();
185
186 while (d->value + n > d->max)
187 d->cond.wait(&(d->mutex));
188
189 d->value += n;
190
191#ifdef QT_CHECK_RANGE
192 if (d->value > d->max) {
193 qWarning("QSemaphore::operator+=: attempt to allocate more resources than available");
194 d->value = d->max;
195 }
196#endif
197
198 ret = d->value;
199
200 d->mutex.unlock();
201
202 return ret;
203}
204
205
206/*!
207 Release \a n accesses to the semaphore.
208*/
209int QSemaphore::operator-=(int n)
210{
211 int ret;
212
213 d->mutex.lock();
214
215 d->value -= n;
216
217#ifdef QT_CHECK_RANGE
218 if (d->value < 0) {
219 qWarning("QSemaphore::operator-=: attempt to deallocate more resources than taken");
220 d->value = 0;
221 }
222#endif
223
224 ret = d->value;
225
226 d->cond.wakeOne();
227 d->mutex.unlock();
228
229 return ret;
230}
231
232
233/*!
234 Returns the number of accesses currently available to the
235 semaphore.
236*/
237int QSemaphore::available() const {
238 int ret;
239
240 d->mutex.lock();
241 ret = d->max - d->value;
242 d->mutex.unlock();
243
244 return ret;
245}
246
247
248/*!
249 Returns the total number of accesses to the semaphore.
250*/
251int QSemaphore::total() const {
252 int ret;
253
254 d->mutex.lock();
255 ret = d->max;
256 d->mutex.unlock();
257
258 return ret;
259}
260
261
262/*!
263 Try to get access to the semaphore. If \l available() \< \a n, this
264 function will return FALSE immediately. If \l available() \>= \a n,
265 this function will take \a n accesses and return TRUE. This
266 function does \e not block.
267*/
268bool QSemaphore::tryAccess(int n)
269{
270 if (! d->mutex.tryLock())
271 return FALSE;
272
273 if (d->value + n > d->max) {
274 d->mutex.unlock();
275 return FALSE;
276 }
277
278 d->value += n;
279
280#ifdef QT_CHECK_RANGE
281 if (d->value > d->max) {
282 qWarning("QSemaphore::operator+=: attempt to allocate more resources than available");
283 d->value = d->max;
284 }
285#endif
286
287 d->mutex.unlock();
288
289 return TRUE;
290}
291
292#endif // QT_THREAD_SUPPORT