source: trunk/src/qt3support/tools/q3semaphore.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 6.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt3Support module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "q3semaphore.h"
43
44#include "qmutex.h"
45#include "qwaitcondition.h"
46
47QT_BEGIN_NAMESPACE
48
49/*!
50 \class Q3Semaphore
51 \threadsafe
52 \brief The Q3Semaphore class provides a robust integer semaphore.
53
54 \compat
55
56 A Q3Semaphore can be used to serialize thread execution, in a
57 similar way to a QMutex. A semaphore differs from a mutex, in
58 that a semaphore can be accessed by more than one thread at a
59 time.
60
61 For example, suppose we have an application that stores data in a
62 large tree structure. The application creates 10 threads
63 (commonly called a thread pool) to perform searches on the tree.
64 When the application searches the tree for some piece of data, it
65 uses one thread per base node to do the searching. A semaphore
66 could be used to make sure that two threads don't try to search
67 the same branch of the tree at the same time.
68
69 A non-computing example of a semaphore would be dining at a
70 restaurant. A semaphore is initialized to have a maximum count
71 equal to the number of chairs in the restaurant. As people
72 arrive, they want a seat. As seats are filled, the semaphore is
73 accessed, once per person. As people leave, the access is
74 released, allowing more people to enter. If a party of 10 people
75 want to be seated, but there are only 9 seats, those 10 people
76 will wait, but a party of 4 people would be seated (taking the
77 available seats to 5, making the party of 10 people wait longer).
78
79 When a semaphore is created it is given a number which is the
80 maximum number of concurrent accesses it will permit. This amount
81 may be changed using operator++(), operator--(), operator+=() and
82 operator-=(). The number of accesses allowed is retrieved with
83 available(), and the total number with total(). Note that the
84 incrementing functions will block if there aren't enough available
85 accesses. Use tryAccess() if you want to acquire accesses without
86 blocking.
87*/
88
89#ifdef max
90#undef max
91#endif
92
93class Q3SemaphorePrivate {
94public:
95 Q3SemaphorePrivate(int);
96
97 QMutex mutex;
98 QWaitCondition cond;
99
100 int value, max;
101};
102
103
104Q3SemaphorePrivate::Q3SemaphorePrivate(int m)
105 : value(0), max(m)
106{
107}
108
109
110/*!
111 Creates a new semaphore. The semaphore can be concurrently
112 accessed at most \a maxcount times.
113*/
114Q3Semaphore::Q3Semaphore(int maxcount)
115{
116 d = new Q3SemaphorePrivate(maxcount);
117}
118
119
120/*!
121 Destroys the semaphore.
122
123 \warning If you destroy a semaphore that has accesses in use the
124 resultant behavior is undefined.
125*/
126Q3Semaphore::~Q3Semaphore()
127{
128 delete d;
129}
130
131
132/*!
133 Postfix ++ operator.
134
135 Try to get access to the semaphore. If \l available() == 0, this
136 call will block until it can get access, i.e. until available() \>
137 0.
138*/
139int Q3Semaphore::operator++(int)
140{
141 QMutexLocker locker(&d->mutex);
142 while (d->value >= d->max)
143 d->cond.wait(locker.mutex());
144
145 ++d->value;
146 if (d->value > d->max)
147 d->value = d->max;
148
149 return d->value;
150}
151
152
153/*!
154 Postfix -- operator.
155
156 Release access of the semaphore. This wakes all threads waiting
157 for access to the semaphore.
158*/
159int Q3Semaphore::operator--(int)
160{
161 QMutexLocker locker(&d->mutex);
162
163 --d->value;
164 if (d->value < 0)
165 d->value = 0;
166
167 d->cond.wakeAll();
168
169 return d->value;
170}
171
172
173/*!
174 Try to get access to the semaphore. If \l available() \< \a n, this
175 call will block until it can get all the accesses it wants, i.e.
176 until available() \>= \a n.
177*/
178int Q3Semaphore::operator+=(int n)
179{
180 QMutexLocker locker(&d->mutex);
181
182 if (n < 0 || n > d->max) {
183 qWarning("Q3Semaphore::operator+=: parameter %d out of range", n);
184 n = n < 0 ? 0 : d->max;
185 }
186
187 while (d->value + n > d->max)
188 d->cond.wait(locker.mutex());
189
190 d->value += n;
191
192 return d->value;
193}
194
195
196/*!
197 Release \a n accesses to the semaphore.
198*/
199int Q3Semaphore::operator-=(int n)
200{
201 QMutexLocker locker(&d->mutex);
202
203 if (n < 0 || n > d->value) {
204 qWarning("Q3Semaphore::operator-=: parameter %d out of range", n);
205 n = n < 0 ? 0 : d->value;
206 }
207
208 d->value -= n;
209 d->cond.wakeAll();
210
211 return d->value;
212}
213
214
215/*!
216 Returns the number of accesses currently available to the
217 semaphore.
218*/
219int Q3Semaphore::available() const
220{
221 QMutexLocker locker(&d->mutex);
222 return d->max - d->value;
223}
224
225
226/*!
227 Returns the total number of accesses to the semaphore.
228*/
229int Q3Semaphore::total() const
230{
231 QMutexLocker locker(&d->mutex);
232 return d->max;
233}
234
235
236/*!
237 Try to get access to the semaphore. If \l available() \< \a n, this
238 function will return false immediately. If \l available() \>= \a n,
239 this function will take \a n accesses and return true. This
240 function does \e not block.
241*/
242bool Q3Semaphore::tryAccess(int n)
243{
244 QMutexLocker locker(&d->mutex);
245
246 if (d->value + n > d->max)
247 return false;
248
249 d->value += n;
250
251 return true;
252}
253
254QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.