source: trunk/src/tools/qsemaphore.cpp@ 75

Last change on this file since 75 was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 6.7 KB
Line 
1/****************************************************************************
2** $Id: qsemaphore.cpp 2 2005-11-16 15:49:26Z dmik $
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 for Unix/X11 or for Qt/Embedded may use this file in accordance
23** with the Qt Commercial License 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. Accesses to
78 the sempahore are gained using operator++() or operator+=(), and
79 released with operator--() or operator-=(). The number of
80 accesses allowed is retrieved with available(), and the total
81 number with total(). Note that the incrementing functions will
82 block if there aren't enough available accesses. Use tryAccess()
83 if you want to acquire accesses without 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 QMutexLocker locker(&d->mutex);
136 while (d->value >= d->max)
137 d->cond.wait(locker.mutex());
138
139 ++d->value;
140 if (d->value > d->max)
141 d->value = d->max;
142
143 return d->value;
144}
145
146
147/*!
148 Postfix -- operator.
149
150 Release access of the semaphore. This wakes all threads waiting
151 for access to the semaphore.
152*/
153int QSemaphore::operator--(int)
154{
155 QMutexLocker locker(&d->mutex);
156
157 --d->value;
158 if (d->value < 0)
159 d->value = 0;
160
161 d->cond.wakeAll();
162
163 return d->value;
164}
165
166
167/*!
168 Try to get access to the semaphore. If \l available() \< \a n, this
169 call will block until it can get all the accesses it wants, i.e.
170 until available() \>= \a n.
171*/
172int QSemaphore::operator+=(int n)
173{
174 QMutexLocker locker(&d->mutex);
175
176 if ( n < 0 || n > d->max ) {
177#ifdef QT_CHECK_RANGE
178 qWarning( "QSemaphore::operator+=: paramter %d out of range", n );
179#endif // QT_CHECK_RANGE
180 n = n < 0 ? 0 : d->max;
181 }
182
183 while (d->value + n > d->max)
184 d->cond.wait(locker.mutex());
185
186 d->value += n;
187
188 return d->value;
189}
190
191
192/*!
193 Release \a n accesses to the semaphore.
194*/
195int QSemaphore::operator-=(int n)
196{
197 QMutexLocker locker(&d->mutex);
198
199 if ( n < 0 || n > d->value ) {
200#ifdef QT_CHECK_RANGE
201 qWarning( "QSemaphore::operator-=: paramter %d out of range", n );
202#endif // QT_CHECK_RANGE
203 n = n < 0 ? 0 : d->value;
204 }
205
206 d->value -= n;
207 d->cond.wakeOne();
208
209 return d->value;
210}
211
212
213/*!
214 Returns the number of accesses currently available to the
215 semaphore.
216*/
217int QSemaphore::available() const
218{
219 QMutexLocker locker(&d->mutex);
220 return d->max - d->value;
221}
222
223
224/*!
225 Returns the total number of accesses to the semaphore.
226*/
227int QSemaphore::total() const
228{
229 QMutexLocker locker(&d->mutex);
230 return d->max;
231}
232
233
234/*!
235 Try to get access to the semaphore. If \l available() \< \a n, this
236 function will return FALSE immediately. If \l available() \>= \a n,
237 this function will take \a n accesses and return TRUE. This
238 function does \e not block.
239*/
240bool QSemaphore::tryAccess(int n)
241{
242 QMutexLocker locker(&d->mutex);
243
244 if (d->value + n > d->max)
245 return FALSE;
246
247 d->value += n;
248
249 return TRUE;
250}
251
252#endif // QT_THREAD_SUPPORT
Note: See TracBrowser for help on using the repository browser.