author | kergoth <kergoth> | 2002-11-01 00:10:42 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-11-01 00:10:42 (UTC) |
commit | 5042e3cf0d3514552769e441f5aad590c8eaf967 (patch) (unidiff) | |
tree | 4a5ea45f3519d981a172ab5275bf38c6fa778dec /qmake/tools/qmutex_unix.cpp | |
parent | 108c1c753e74e989cc13923086996791428c9af4 (diff) | |
download | opie-5042e3cf0d3514552769e441f5aad590c8eaf967.zip opie-5042e3cf0d3514552769e441f5aad590c8eaf967.tar.gz opie-5042e3cf0d3514552769e441f5aad590c8eaf967.tar.bz2 |
Adding qmake in preperation for new build system
-rw-r--r-- | qmake/tools/qmutex_unix.cpp | 687 |
1 files changed, 687 insertions, 0 deletions
diff --git a/qmake/tools/qmutex_unix.cpp b/qmake/tools/qmutex_unix.cpp new file mode 100644 index 0000000..c861b2d --- a/dev/null +++ b/qmake/tools/qmutex_unix.cpp | |||
@@ -0,0 +1,687 @@ | |||
1 | /**************************************************************************** | ||
2 | ** $Id$ | ||
3 | ** | ||
4 | ** QMutex 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 | |||
42 | typedef pthread_mutex_t Q_MUTEX_T; | ||
43 | |||
44 | // POSIX threads mutex types | ||
45 | #if ((defined(PTHREAD_MUTEX_RECURSIVE) && defined(PTHREAD_MUTEX_DEFAULT)) || \ | ||
46 | defined(Q_OS_FREEBSD)) && !defined(Q_OS_UNIXWARE) && !defined(Q_OS_SOLARIS) | ||
47 | // POSIX 1003.1c-1995 - We love this OS | ||
48 | # define Q_MUTEX_SET_TYPE(a, b) pthread_mutexattr_settype((a), (b)) | ||
49 | # if defined(QT_CHECK_RANGE) | ||
50 | # define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK | ||
51 | # else | ||
52 | # define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT | ||
53 | # endif | ||
54 | # define Q_RECURSIVE_MUTEX_TYPE PTHREAD_MUTEX_RECURSIVE | ||
55 | #elif defined(MUTEX_NONRECURSIVE_NP) && defined(MUTEX_RECURSIVE_NP) | ||
56 | // POSIX 1003.4a pthreads draft extensions | ||
57 | # define Q_MUTEX_SET_TYPE(a, b) pthread_mutexattr_setkind_np((a), (b)); | ||
58 | # define Q_NORMAL_MUTEX_TYPE MUTEX_NONRECURSIVE_NP | ||
59 | # define Q_RECURSIVE_MUTEX_TYPE MUTEX_RECURSIVE_NP | ||
60 | #else | ||
61 | // Unknown mutex types - skip them | ||
62 | # define Q_MUTEX_SET_TYPE(a, b) | ||
63 | # undef Q_NORMAL_MUTEX_TYPE | ||
64 | # undef Q_RECURSIVE_MUTEX_TYPE | ||
65 | #endif | ||
66 | |||
67 | #include "qmutex.h" | ||
68 | #include "qmutex_p.h" | ||
69 | |||
70 | #include <errno.h> | ||
71 | #include <string.h> | ||
72 | |||
73 | |||
74 | // Private class declarations | ||
75 | |||
76 | class QRealMutexPrivate : public QMutexPrivate { | ||
77 | public: | ||
78 | QRealMutexPrivate(bool = FALSE); | ||
79 | |||
80 | void lock(); | ||
81 | void unlock(); | ||
82 | bool locked(); | ||
83 | bool trylock(); | ||
84 | int type() const; | ||
85 | |||
86 | bool recursive; | ||
87 | }; | ||
88 | |||
89 | #ifndef Q_RECURSIVE_MUTEX_TYPE | ||
90 | class QRecursiveMutexPrivate : public QMutexPrivate | ||
91 | { | ||
92 | public: | ||
93 | QRecursiveMutexPrivate(); | ||
94 | ~QRecursiveMutexPrivate(); | ||
95 | |||
96 | void lock(); | ||
97 | void unlock(); | ||
98 | bool locked(); | ||
99 | bool trylock(); | ||
100 | int type() const; | ||
101 | |||
102 | int count; | ||
103 | unsigned long owner; | ||
104 | pthread_mutex_t handle2; | ||
105 | }; | ||
106 | #endif // !Q_RECURSIVE_MUTEX_TYPE | ||
107 | |||
108 | |||
109 | // Private class implementation | ||
110 | |||
111 | // base destructor | ||
112 | QMutexPrivate::~QMutexPrivate() | ||
113 | { | ||
114 | int ret = pthread_mutex_destroy(&handle); | ||
115 | |||
116 | #ifdef QT_CHECK_RANGE | ||
117 | if ( ret ) | ||
118 | qWarning( "Mutex destroy failure: %s", strerror( ret ) ); | ||
119 | #endif | ||
120 | } | ||
121 | |||
122 | // real mutex class | ||
123 | QRealMutexPrivate::QRealMutexPrivate(bool recurs) | ||
124 | : recursive(recurs) | ||
125 | { | ||
126 | pthread_mutexattr_t attr; | ||
127 | pthread_mutexattr_init(&attr); | ||
128 | Q_MUTEX_SET_TYPE(&attr, recursive ? Q_RECURSIVE_MUTEX_TYPE : Q_NORMAL_MUTEX_TYPE); | ||
129 | Q_UNUSED(recursive); | ||
130 | int ret = pthread_mutex_init(&handle, &attr); | ||
131 | pthread_mutexattr_destroy(&attr); | ||
132 | |||
133 | #ifdef QT_CHECK_RANGE | ||
134 | if( ret ) | ||
135 | qWarning( "Mutex init failure: %s", strerror( ret ) ); | ||
136 | #endif // QT_CHECK_RANGE | ||
137 | } | ||
138 | |||
139 | void QRealMutexPrivate::lock() | ||
140 | { | ||
141 | int ret = pthread_mutex_lock(&handle); | ||
142 | |||
143 | #ifdef QT_CHECK_RANGE | ||
144 | if (ret) | ||
145 | qWarning("Mutex lock failure: %s", strerror(ret)); | ||
146 | #endif | ||
147 | } | ||
148 | |||
149 | void QRealMutexPrivate::unlock() | ||
150 | { | ||
151 | int ret = pthread_mutex_unlock(&handle); | ||
152 | |||
153 | #ifdef QT_CHECK_RANGE | ||
154 | if (ret) | ||
155 | qWarning("Mutex unlock failure: %s", strerror(ret)); | ||
156 | #endif | ||
157 | } | ||
158 | |||
159 | bool QRealMutexPrivate::locked() | ||
160 | { | ||
161 | int ret = pthread_mutex_trylock(&handle); | ||
162 | |||
163 | if (ret == EBUSY) { | ||
164 | return TRUE; | ||
165 | } else if (ret) { | ||
166 | #ifdef QT_CHECK_RANGE | ||
167 | qWarning("Mutex locktest failure: %s", strerror(ret)); | ||
168 | #endif | ||
169 | } else | ||
170 | pthread_mutex_unlock(&handle); | ||
171 | |||
172 | return FALSE; | ||
173 | } | ||
174 | |||
175 | bool QRealMutexPrivate::trylock() | ||
176 | { | ||
177 | int ret = pthread_mutex_trylock(&handle); | ||
178 | |||
179 | if (ret == EBUSY) { | ||
180 | return FALSE; | ||
181 | } else if (ret) { | ||
182 | #ifdef QT_CHECK_RANGE | ||
183 | qWarning("Mutex trylock failure: %s", strerror(ret)); | ||
184 | #endif | ||
185 | return FALSE; | ||
186 | } | ||
187 | |||
188 | return TRUE; | ||
189 | } | ||
190 | |||
191 | int QRealMutexPrivate::type() const | ||
192 | { | ||
193 | return recursive ? Q_MUTEX_RECURSIVE : Q_MUTEX_NORMAL; | ||
194 | } | ||
195 | |||
196 | |||
197 | #ifndef Q_RECURSIVE_MUTEX_TYPE | ||
198 | QRecursiveMutexPrivate::QRecursiveMutexPrivate() | ||
199 | : count(0), owner(0) | ||
200 | { | ||
201 | pthread_mutexattr_t attr; | ||
202 | pthread_mutexattr_init(&attr); | ||
203 | Q_MUTEX_SET_TYPE(&attr, Q_NORMAL_MUTEX_TYPE); | ||
204 | int ret = pthread_mutex_init(&handle, &attr); | ||
205 | pthread_mutexattr_destroy(&attr); | ||
206 | |||
207 | # ifdef QT_CHECK_RANGE | ||
208 | if (ret) | ||
209 | qWarning( "Mutex init failure: %s", strerror(ret) ); | ||
210 | # endif | ||
211 | |||
212 | pthread_mutexattr_init(&attr); | ||
213 | ret = pthread_mutex_init( &handle2, &attr ); | ||
214 | pthread_mutexattr_destroy(&attr); | ||
215 | |||
216 | # ifdef QT_CHECK_RANGE | ||
217 | if (ret) | ||
218 | qWarning( "Mutex init failure: %s", strerror(ret) ); | ||
219 | # endif | ||
220 | } | ||
221 | |||
222 | QRecursiveMutexPrivate::~QRecursiveMutexPrivate() | ||
223 | { | ||
224 | int ret = pthread_mutex_destroy(&handle2); | ||
225 | |||
226 | # ifdef QT_CHECK_RANGE | ||
227 | if (ret) | ||
228 | qWarning( "Mutex destroy failure: %s", strerror(ret) ); | ||
229 | # endif | ||
230 | } | ||
231 | |||
232 | void QRecursiveMutexPrivate::lock() | ||
233 | { | ||
234 | pthread_mutex_lock(&handle2); | ||
235 | |||
236 | if (count > 0 && owner == (unsigned long) pthread_self()) { | ||
237 | count++; | ||
238 | } else { | ||
239 | pthread_mutex_unlock(&handle2); | ||
240 | pthread_mutex_lock(&handle); | ||
241 | pthread_mutex_lock(&handle2); | ||
242 | count = 1; | ||
243 | owner = (unsigned long) pthread_self(); | ||
244 | } | ||
245 | |||
246 | pthread_mutex_unlock(&handle2); | ||
247 | } | ||
248 | |||
249 | void QRecursiveMutexPrivate::unlock() | ||
250 | { | ||
251 | pthread_mutex_lock(&handle2); | ||
252 | |||
253 | if (owner == (unsigned long) pthread_self()) { | ||
254 | // do nothing if the count is already 0... to reflect the behaviour described | ||
255 | // in the docs | ||
256 | if (count && (--count) < 1) { | ||
257 | count = 0; | ||
258 | pthread_mutex_unlock(&handle); | ||
259 | } | ||
260 | } else { | ||
261 | #ifdef QT_CHECK_RANGE | ||
262 | qWarning("QMutex::unlock: unlock from different thread than locker"); | ||
263 | qWarning(" was locked by %d, unlock attempt from %d", | ||
264 | (int)owner, (int)pthread_self()); | ||
265 | #endif | ||
266 | } | ||
267 | |||
268 | pthread_mutex_unlock(&handle2); | ||
269 | } | ||
270 | |||
271 | bool QRecursiveMutexPrivate::locked() | ||
272 | { | ||
273 | pthread_mutex_lock(&handle2); | ||
274 | |||
275 | bool ret; | ||
276 | int code = pthread_mutex_trylock(&handle); | ||
277 | |||
278 | if (code == EBUSY) { | ||
279 | ret = TRUE; | ||
280 | } else { | ||
281 | #ifdef QT_CHECK_RANGE | ||
282 | if (code) | ||
283 | qWarning("Mutex trylock failure: %s", strerror(code)); | ||
284 | #endif | ||
285 | |||
286 | pthread_mutex_unlock(&handle); | ||
287 | ret = FALSE; | ||
288 | } | ||
289 | |||
290 | pthread_mutex_unlock(&handle2); | ||
291 | |||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | bool QRecursiveMutexPrivate::trylock() | ||
296 | { | ||
297 | bool ret = TRUE; | ||
298 | |||
299 | pthread_mutex_lock(&handle2); | ||
300 | |||
301 | if ( count > 0 && owner == (unsigned long) pthread_self() ) { | ||
302 | count++; | ||
303 | } else { | ||
304 | int code = pthread_mutex_trylock(&handle); | ||
305 | |||
306 | if (code == EBUSY) { | ||
307 | ret = FALSE; | ||
308 | } else if (code) { | ||
309 | #ifdef QT_CHECK_RANGE | ||
310 | qWarning("Mutex trylock failure: %s", strerror(code)); | ||
311 | #endif | ||
312 | ret = FALSE; | ||
313 | } else { | ||
314 | count = 1; | ||
315 | owner = (unsigned long) pthread_self(); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | pthread_mutex_unlock(&handle2); | ||
320 | |||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | int QRecursiveMutexPrivate::type() const | ||
325 | { | ||
326 | return Q_MUTEX_RECURSIVE; | ||
327 | } | ||
328 | |||
329 | #endif // !Q_RECURSIVE_MUTEX_TYPE | ||
330 | |||
331 | |||
332 | /*! | ||
333 | \class QMutex qmutex.h | ||
334 | \threadsafe | ||
335 | \brief The QMutex class provides access serialization between threads. | ||
336 | |||
337 | \ingroup thread | ||
338 | \ingroup environment | ||
339 | |||
340 | The purpose of a QMutex is to protect an object, data structure or | ||
341 | section of code so that only one thread can access it at a time | ||
342 | (This is similar to the Java \c synchronized keyword). For | ||
343 | example, say there is a method which prints a message to the user | ||
344 | on two lines: | ||
345 | |||
346 | \code | ||
347 | int number = 6; | ||
348 | |||
349 | void method1() | ||
350 | { | ||
351 | number *= 5; | ||
352 | number /= 4; | ||
353 | } | ||
354 | |||
355 | void method1() | ||
356 | { | ||
357 | number *= 3; | ||
358 | number /= 2; | ||
359 | } | ||
360 | \endcode | ||
361 | |||
362 | If these two methods are called in succession, the following happens: | ||
363 | |||
364 | \code | ||
365 | // method1() | ||
366 | number *= 5;// number is now 30 | ||
367 | number /= 4;// number is now 7 | ||
368 | |||
369 | // method2() | ||
370 | number *= 3;// nubmer is now 21 | ||
371 | number /= 2;// number is now 10 | ||
372 | \endcode | ||
373 | |||
374 | If these two methods are called simultaneously from two threads then the | ||
375 | following sequence could result: | ||
376 | |||
377 | \code | ||
378 | // Thread 1 calls method1() | ||
379 | number *= 5;// number is now 30 | ||
380 | |||
381 | // Thread 2 calls method2(). | ||
382 | // | ||
383 | // Most likely Thread 1 has been put to sleep by the operating | ||
384 | // system to allow Thread 2 to run. | ||
385 | number *= 3;// number is now 90 | ||
386 | number /= 2;// number is now 45 | ||
387 | |||
388 | // Thread 1 finishes executing. | ||
389 | number /= 4;// number is now 11, instead of 10 | ||
390 | \endcode | ||
391 | |||
392 | If we add a mutex, we should get the result we want: | ||
393 | |||
394 | \code | ||
395 | QMutex mutex; | ||
396 | int number = 6; | ||
397 | |||
398 | void method1() | ||
399 | { | ||
400 | mutex.lock(); | ||
401 | number *= 5; | ||
402 | number /= 4; | ||
403 | mutex.unlock(); | ||
404 | } | ||
405 | |||
406 | void method2() | ||
407 | { | ||
408 | mutex.lock(); | ||
409 | number *= 3; | ||
410 | number /= 2; | ||
411 | mutex.unlock(); | ||
412 | } | ||
413 | \endcode | ||
414 | |||
415 | Then only one thread can modify \c number at any given time and | ||
416 | the result is correct. This is a trivial example, of course, but | ||
417 | applies to any other case where things need to happen in a | ||
418 | particular sequence. | ||
419 | |||
420 | When you call lock() in a thread, other threads that try to call | ||
421 | lock() in the same place will block until the thread that got the | ||
422 | lock calls unlock(). A non-blocking alternative to lock() is | ||
423 | tryLock(). | ||
424 | */ | ||
425 | |||
426 | /*! | ||
427 | Constructs a new mutex. The mutex is created in an unlocked state. | ||
428 | A recursive mutex is created if \a recursive is TRUE; a normal | ||
429 | mutex is created if \a recursive is FALSE (the default). With a | ||
430 | recursive mutex, a thread can lock the same mutex multiple times | ||
431 | and it will not be unlocked until a corresponding number of | ||
432 | unlock() calls have been made. | ||
433 | */ | ||
434 | QMutex::QMutex(bool recursive) | ||
435 | { | ||
436 | #ifndef Q_RECURSIVE_MUTEX_TYPE | ||
437 | if ( recursive ) | ||
438 | d = new QRecursiveMutexPrivate(); | ||
439 | else | ||
440 | #endif // !Q_RECURSIVE_MUTEX_TYPE | ||
441 | d = new QRealMutexPrivate(recursive); | ||
442 | } | ||
443 | |||
444 | /*! | ||
445 | Destroys the mutex. | ||
446 | |||
447 | \warning If you destroy a mutex that still holds a lock the | ||
448 | resultant behavior is undefined. | ||
449 | */ | ||
450 | QMutex::~QMutex() | ||
451 | { | ||
452 | delete d; | ||
453 | } | ||
454 | |||
455 | /*! | ||
456 | Attempt to lock the mutex. If another thread has locked the mutex | ||
457 | then this call will \e block until that thread has unlocked it. | ||
458 | |||
459 | \sa unlock(), locked() | ||
460 | */ | ||
461 | void QMutex::lock() | ||
462 | { | ||
463 | d->lock(); | ||
464 | } | ||
465 | |||
466 | /*! | ||
467 | Unlocks the mutex. Attempting to unlock a mutex in a different | ||
468 | thread to the one that locked it results in an error. Unlocking a | ||
469 | mutex that is not locked results in undefined behaviour (varies | ||
470 | between different Operating Systems' thread implementations). | ||
471 | |||
472 | \sa lock(), locked() | ||
473 | */ | ||
474 | void QMutex::unlock() | ||
475 | { | ||
476 | d->unlock(); | ||
477 | } | ||
478 | |||
479 | /*! | ||
480 | Returns TRUE if the mutex is locked by another thread; otherwise | ||
481 | returns FALSE. | ||
482 | |||
483 | \warning Due to differing implementations of recursive mutexes on | ||
484 | various platforms, calling this function from the same thread that | ||
485 | previously locked the mutex will return undefined results. | ||
486 | |||
487 | \sa lock(), unlock() | ||
488 | */ | ||
489 | bool QMutex::locked() | ||
490 | { | ||
491 | return d->locked(); | ||
492 | } | ||
493 | |||
494 | /*! | ||
495 | Attempt to lock the mutex. If the lock was obtained, this function | ||
496 | returns TRUE. If another thread has locked the mutex, this | ||
497 | function returns FALSE, instead of waiting for the mutex to become | ||
498 | available, i.e. it does not block. | ||
499 | |||
500 | If the lock was obtained, the mutex must be unlocked with unlock() | ||
501 | before another thread can successfully lock it. | ||
502 | |||
503 | \sa lock(), unlock(), locked() | ||
504 | */ | ||
505 | bool QMutex::tryLock() | ||
506 | { | ||
507 | return d->trylock(); | ||
508 | } | ||
509 | |||
510 | /*! | ||
511 | \class QMutexLocker qmutex.h | ||
512 | \brief The QMutexLocker class simplifies locking and unlocking QMutexes. | ||
513 | |||
514 | \threadsafe | ||
515 | |||
516 | \ingroup thread | ||
517 | \ingroup environment | ||
518 | |||
519 | The purpose of QMutexLocker is to simplify QMutex locking and | ||
520 | unlocking. Locking and unlocking a QMutex in complex functions and | ||
521 | statements or in exception handling code is error prone and | ||
522 | difficult to debug. QMutexLocker should be used in such situations | ||
523 | to ensure that the state of the mutex is well defined and always | ||
524 | locked and unlocked properly. | ||
525 | |||
526 | QMutexLocker should be created within a function where a QMutex | ||
527 | needs to be locked. The mutex is locked when QMutexLocker is | ||
528 | created, and unlocked when QMutexLocker is destroyed. | ||
529 | |||
530 | For example, this complex function locks a QMutex upon entering | ||
531 | the function and unlocks the mutex at all the exit points: | ||
532 | |||
533 | \code | ||
534 | int complexFunction( int flag ) | ||
535 | { | ||
536 | mutex.lock(); | ||
537 | |||
538 | int return_value = 0; | ||
539 | |||
540 | switch ( flag ) { | ||
541 | case 0: | ||
542 | case 1: | ||
543 | { | ||
544 | mutex.unlock(); | ||
545 | return moreComplexFunction( flag ); | ||
546 | } | ||
547 | |||
548 | case 2: | ||
549 | { | ||
550 | int status = anotherFunction(); | ||
551 | if ( status < 0 ) { | ||
552 | mutex.unlock(); | ||
553 | return -2; | ||
554 | } | ||
555 | return_value = status + flag; | ||
556 | break; | ||
557 | } | ||
558 | |||
559 | default: | ||
560 | { | ||
561 | if ( flag > 10 ) { | ||
562 | mutex.unlock(); | ||
563 | return -1; | ||
564 | } | ||
565 | break; | ||
566 | } | ||
567 | } | ||
568 | |||
569 | mutex.unlock(); | ||
570 | return return_value; | ||
571 | } | ||
572 | \endcode | ||
573 | |||
574 | This example function will get more complicated as it is | ||
575 | developed, which increases the likelihood that errors will occur. | ||
576 | |||
577 | Using QMutexLocker greatly simplifies the code, and makes it more | ||
578 | readable: | ||
579 | |||
580 | \code | ||
581 | int complexFunction( int flag ) | ||
582 | { | ||
583 | QMutexLocker locker( &mutex ); | ||
584 | |||
585 | int return_value = 0; | ||
586 | |||
587 | switch ( flag ) { | ||
588 | case 0: | ||
589 | case 1: | ||
590 | { | ||
591 | return moreComplexFunction( flag ); | ||
592 | } | ||
593 | |||
594 | case 2: | ||
595 | { | ||
596 | int status = anotherFunction(); | ||
597 | if ( status < 0 ) | ||
598 | return -2; | ||
599 | return_value = status + flag; | ||
600 | break; | ||
601 | } | ||
602 | |||
603 | default: | ||
604 | { | ||
605 | if ( flag > 10 ) | ||
606 | return -1; | ||
607 | break; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | return return_value; | ||
612 | } | ||
613 | \endcode | ||
614 | |||
615 | Now, the mutex will always be unlocked when the QMutexLocker | ||
616 | object is destroyed (when the function returns since \c locker is | ||
617 | an auto variable). | ||
618 | |||
619 | The same principle applies to code that throws and catches | ||
620 | exceptions. An exception that is not caught in the function that | ||
621 | has locked the mutex has no way of unlocking the mutex before the | ||
622 | exception is passed up the stack to the calling function. | ||
623 | |||
624 | QMutexLocker also provides a mutex() member function that returns | ||
625 | the mutex on which the QMutexLocker is operating. This is useful | ||
626 | for code that needs access to the mutex, such as | ||
627 | QWaitCondition::wait(). For example: | ||
628 | |||
629 | \code | ||
630 | class SignalWaiter | ||
631 | { | ||
632 | private: | ||
633 | QMutexLocker locker; | ||
634 | |||
635 | public: | ||
636 | SignalWaiter( QMutex *mutex ) | ||
637 | : locker( mutex ) | ||
638 | { | ||
639 | } | ||
640 | |||
641 | void waitForSignal() | ||
642 | { | ||
643 | ... | ||
644 | ... | ||
645 | ... | ||
646 | |||
647 | while ( ! signalled ) | ||
648 | waitcondition.wait( locker.mutex() ); | ||
649 | |||
650 | ... | ||
651 | ... | ||
652 | ... | ||
653 | } | ||
654 | }; | ||
655 | \endcode | ||
656 | |||
657 | \sa QMutex, QWaitCondition | ||
658 | */ | ||
659 | |||
660 | /*! | ||
661 | \fn QMutexLocker::QMutexLocker( QMutex *mutex ) | ||
662 | |||
663 | Constructs a QMutexLocker and locks \a mutex. The mutex will be | ||
664 | unlocked when the QMutexLocker is destroyed. | ||
665 | |||
666 | \sa QMutex::lock() | ||
667 | */ | ||
668 | |||
669 | /*! | ||
670 | \fn QMutexLocker::~QMutexLocker() | ||
671 | |||
672 | Destroys the QMutexLocker and unlocks the mutex which was locked | ||
673 | in the constructor. | ||
674 | |||
675 | \sa QMutexLocker::QMutexLocker(), QMutex::unlock() | ||
676 | */ | ||
677 | |||
678 | /*! | ||
679 | \fn QMutex *QMutexLocker::mutex() const | ||
680 | |||
681 | Returns a pointer to the mutex which was locked in the | ||
682 | constructor. | ||
683 | |||
684 | \sa QMutexLocker::QMutexLocker() | ||
685 | */ | ||
686 | |||
687 | #endif // QT_THREAD_SUPPORT | ||