summaryrefslogtreecommitdiff
path: root/qmake/tools/qwaitcondition_unix.cpp
Unidiff
Diffstat (limited to 'qmake/tools/qwaitcondition_unix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--qmake/tools/qwaitcondition_unix.cpp310
1 files changed, 310 insertions, 0 deletions
diff --git a/qmake/tools/qwaitcondition_unix.cpp b/qmake/tools/qwaitcondition_unix.cpp
new file mode 100644
index 0000000..99c1014
--- a/dev/null
+++ b/qmake/tools/qwaitcondition_unix.cpp
@@ -0,0 +1,310 @@
1/****************************************************************************
2** $Id$
3**
4** QWaitCondition 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 "qplatformdefs.h"
41
42typedef pthread_mutex_t Q_MUTEX_T;
43
44#include "qwaitcondition.h"
45#include "qmutex.h"
46#include "qmutex_p.h"
47
48#include <errno.h>
49#include <string.h>
50
51
52struct QWaitConditionPrivate {
53 pthread_cond_t cond;
54};
55
56
57/*!
58 \class QWaitCondition qwaitcondition.h
59 \threadsafe
60 \brief The QWaitCondition class allows waiting/waking for conditions between threads.
61
62 \ingroup thread
63 \ingroup environment
64
65 QWaitConditions allow a thread to tell other threads that some
66 sort of condition has been met; one or many threads can block
67 waiting for a QWaitCondition to set a condition with wakeOne() or
68 wakeAll(). Use wakeOne() to wake one randomly selected event or
69 wakeAll() to wake them all. For example, say we have three tasks
70 that should be performed every time the user presses a key; each
71 task could be split into a thread, each of which would have a
72 run() body like this:
73
74 \code
75 QWaitCondition key_pressed;
76
77 for (;;) {
78 key_pressed.wait(); // This is a QWaitCondition global variable
79 // Key was pressed, do something interesting
80 do_something();
81 }
82 \endcode
83
84 A fourth thread would read key presses and wake the other three
85 threads up every time it receives one, like this:
86
87 \code
88 QWaitCondition key_pressed;
89
90 for (;;) {
91 getchar();
92 // Causes any thread in key_pressed.wait() to return from
93 // that method and continue processing
94 key_pressed.wakeAll();
95 }
96 \endcode
97
98 Note that the order the three threads are woken up in is
99 undefined, and that if some or all of the threads are still in
100 do_something() when the key is pressed, they won't be woken up
101 (since they're not waiting on the condition variable) and so the
102 task will not be performed for that key press. This can be
103 avoided by, for example, doing something like this:
104
105 \code
106 QMutex mymutex;
107 QWaitCondition key_pressed;
108 int mycount=0;
109
110 // Worker thread code
111 for (;;) {
112 key_pressed.wait(); // This is a QWaitCondition global variable
113 mymutex.lock();
114 mycount++;
115 mymutex.unlock();
116 do_something();
117 mymutex.lock();
118 mycount--;
119 mymutex.unlock();
120 }
121
122 // Key reading thread code
123 for (;;) {
124 getchar();
125 mymutex.lock();
126 // Sleep until there are no busy worker threads
127 while( count > 0 ) {
128 mymutex.unlock();
129 sleep( 1 );
130 mymutex.lock();
131 }
132 mymutex.unlock();
133 key_pressed.wakeAll();
134 }
135 \endcode
136
137 The mutexes are necessary because the results of two threads
138 attempting to change the value of the same variable simultaneously
139 are unpredictable.
140*/
141
142/*!
143 Constructs a new event signalling, i.e. wait condition, object.
144*/
145QWaitCondition::QWaitCondition()
146{
147 d = new QWaitConditionPrivate;
148
149 int ret = pthread_cond_init(&d->cond, NULL);
150
151#ifdef QT_CHECK_RANGE
152 if (ret)
153 qWarning( "Wait condition init failure: %s", strerror( ret ) );
154#endif
155}
156
157
158/*!
159 Deletes the event signalling, i.e. wait condition, object.
160*/
161QWaitCondition::~QWaitCondition()
162{
163 int ret = pthread_cond_destroy(&d->cond);
164
165 if (ret) {
166#ifdef QT_CHECK_RANGE
167 qWarning( "Wait condition destroy failure: %s", strerror( ret ) );
168#endif
169
170 // seems we have threads waiting on us, lets wake them up
171 pthread_cond_broadcast(&d->cond);
172 }
173
174 delete d;
175}
176
177/*!
178 This wakes one thread waiting on the QWaitCondition. The thread
179 that is woken up depends on the operating system's scheduling
180 policies, and cannot be controlled or predicted.
181
182 \sa wakeAll()
183*/
184void QWaitCondition::wakeOne()
185{
186 int ret = pthread_cond_signal(&d->cond);
187
188#ifdef QT_CHECK_RANGE
189 if (ret)
190 qWarning("Wait condition wakeOne failure: %s", strerror(ret));
191#endif
192}
193
194/*!
195 This wakes all threads waiting on the QWaitCondition. The order in
196 which the threads are woken up depends on the operating system's
197 scheduling policies, and cannot be controlled or predicted.
198
199 \sa wakeOne()
200*/
201void QWaitCondition::wakeAll()
202{
203 int ret = pthread_cond_broadcast(&d->cond);
204
205#ifdef QT_CHECK_RANGE
206 if (ret)
207 qWarning("Wait condition wakeAll failure: %s", strerror(ret));
208#endif
209}
210
211/*!
212 Wait on the thread event object. The thread calling this will
213 block until either of these conditions is met:
214 \list
215 \i Another thread signals it using wakeOne() or wakeAll(). This
216 function will return TRUE in this case.
217 \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the
218 default), then the wait will never timeout (the event must be
219 signalled). This function will return FALSE if the wait timed
220 out.
221 \endlist
222
223 \sa wakeOne(), wakeAll()
224*/
225bool QWaitCondition::wait(unsigned long time)
226{
227 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
228
229 int ret;
230 if (time != ULONG_MAX) {
231 struct timeval tv;
232 gettimeofday(&tv, 0);
233
234 timespec ti;
235 ti.tv_nsec = (tv.tv_usec * 1000) + (time % 1000) * 1000;
236 ti.tv_sec = tv.tv_sec + (time / 1000) + ( ti.tv_nsec / 1000000000 );
237 ti.tv_nsec %= 1000000000;
238
239 ret = pthread_cond_timedwait(&d->cond, &mutex, &ti);
240 } else
241 ret = pthread_cond_wait(&d->cond, &mutex);
242
243#ifdef QT_CHECK_RANGE
244 if (ret && ret != ETIMEDOUT)
245 qWarning("Wait condition wait failure: %s",strerror(ret));
246#endif
247
248 return (ret == 0);
249}
250
251/*!
252 \overload
253
254 Release the locked \a mutex and wait on the thread event object.
255 The \a mutex must be initially locked by the calling thread. If \a
256 mutex is not in a locked state, this function returns immediately.
257 If \a mutex is a recursive mutex, this function returns
258 immediately. The \a mutex will be unlocked, and the calling thread
259 will block until either of these conditions is met:
260 \list
261 \i Another thread signals it using wakeOne() or wakeAll(). This
262 function will return TRUE in this case.
263 \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the
264 default), then the wait will never timeout (the event must be
265 signalled). This function will return FALSE if the wait timed
266 out.
267 \endlist
268
269 The mutex will be returned to the same locked state. This function
270 is provided to allow the atomic transition from the locked state
271 to the wait state.
272
273 \sa wakeOne(), wakeAll()
274*/
275bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
276{
277 if (! mutex)
278 return FALSE;
279
280 if (mutex->d->type() == Q_MUTEX_RECURSIVE) {
281#ifdef QT_CHECK_RANGE
282 qWarning("Wait condition warning: using recursive mutexes with\n"
283 " wait conditions is undefined!");
284#endif
285 return FALSE;
286 }
287
288 int ret;
289 if (time != ULONG_MAX) {
290 struct timeval tv;
291 gettimeofday(&tv, 0);
292
293 timespec ti;
294 ti.tv_nsec = (tv.tv_usec * 1000) + (time % 1000) * 1000;
295 ti.tv_sec = tv.tv_sec + (time / 1000) + ( ti.tv_nsec / 1000000000 );
296 ti.tv_nsec %= 1000000000;
297
298 ret = pthread_cond_timedwait(&d->cond, &mutex->d->handle, &ti);
299 } else
300 ret = pthread_cond_wait(&d->cond, &mutex->d->handle);
301
302#ifdef QT_CHECK_RANGE
303 if (ret && ret != ETIMEDOUT)
304 qWarning("Wait condition wait failure: %s",strerror(ret));
305#endif
306
307 return (ret == 0);
308}
309
310#endif // QT_THREAD_SUPPORT