00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #if defined(QT_THREAD_SUPPORT)
00039
00040 #include "qplatformdefs.h"
00041
00042 typedef pthread_mutex_t Q_MUTEX_T;
00043
00044
00045 #if ((defined(PTHREAD_MUTEX_RECURSIVE) && defined(PTHREAD_MUTEX_DEFAULT)) || \
00046 defined(Q_OS_FREEBSD)) && !defined(Q_OS_UNIXWARE) && !defined(Q_OS_SOLARIS) && \
00047 !defined(Q_OS_MAC)
00048
00049 # define Q_MUTEX_SET_TYPE(a, b) pthread_mutexattr_settype((a), (b))
00050 # if defined(QT_CHECK_RANGE)
00051 # define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK
00052 # else
00053 # define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT
00054 # endif
00055 # define Q_RECURSIVE_MUTEX_TYPE PTHREAD_MUTEX_RECURSIVE
00056 #elif defined(MUTEX_NONRECURSIVE_NP) && defined(MUTEX_RECURSIVE_NP)
00057
00058 # define Q_MUTEX_SET_TYPE(a, b) pthread_mutexattr_setkind_np((a), (b));
00059 # define Q_NORMAL_MUTEX_TYPE MUTEX_NONRECURSIVE_NP
00060 # define Q_RECURSIVE_MUTEX_TYPE MUTEX_RECURSIVE_NP
00061 #else
00062
00063 # define Q_MUTEX_SET_TYPE(a, b)
00064 # undef Q_NORMAL_MUTEX_TYPE
00065 # undef Q_RECURSIVE_MUTEX_TYPE
00066 #endif
00067
00068 #include "qmutex.h"
00069 #include "qmutex_p.h"
00070
00071 #include <errno.h>
00072 #include <string.h>
00073
00074
00075
00076
00077 class QRealMutexPrivate : public QMutexPrivate {
00078 public:
00079 QRealMutexPrivate(bool = FALSE);
00080
00081 void lock();
00082 void unlock();
00083 bool locked();
00084 bool trylock();
00085 int type() const;
00086
00087 bool recursive;
00088 };
00089
00090 #ifndef Q_RECURSIVE_MUTEX_TYPE
00091 class QRecursiveMutexPrivate : public QMutexPrivate
00092 {
00093 public:
00094 QRecursiveMutexPrivate();
00095 ~QRecursiveMutexPrivate();
00096
00097 void lock();
00098 void unlock();
00099 bool locked();
00100 bool trylock();
00101 int type() const;
00102
00103 int count;
00104 unsigned long owner;
00105 pthread_mutex_t handle2;
00106 };
00107 #endif // !Q_RECURSIVE_MUTEX_TYPE
00108
00109
00110
00111
00112
00113 QMutexPrivate::~QMutexPrivate()
00114 {
00115 int ret = pthread_mutex_destroy(&handle);
00116
00117 #ifdef QT_CHECK_RANGE
00118 if ( ret )
00119 qWarning( "Mutex destroy failure: %s", strerror( ret ) );
00120 #endif
00121 }
00122
00123
00124 QRealMutexPrivate::QRealMutexPrivate(bool recurs)
00125 : recursive(recurs)
00126 {
00127 pthread_mutexattr_t attr;
00128 pthread_mutexattr_init(&attr);
00129 Q_MUTEX_SET_TYPE(&attr, recursive ? Q_RECURSIVE_MUTEX_TYPE : Q_NORMAL_MUTEX_TYPE);
00130 Q_UNUSED(recursive);
00131 int ret = pthread_mutex_init(&handle, &attr);
00132 pthread_mutexattr_destroy(&attr);
00133
00134 #ifdef QT_CHECK_RANGE
00135 if( ret )
00136 qWarning( "Mutex init failure: %s", strerror( ret ) );
00137 #endif // QT_CHECK_RANGE
00138 }
00139
00140 void QRealMutexPrivate::lock()
00141 {
00142 int ret = pthread_mutex_lock(&handle);
00143
00144 #ifdef QT_CHECK_RANGE
00145 if (ret)
00146 qWarning("Mutex lock failure: %s", strerror(ret));
00147 #endif
00148 }
00149
00150 void QRealMutexPrivate::unlock()
00151 {
00152 int ret = pthread_mutex_unlock(&handle);
00153
00154 #ifdef QT_CHECK_RANGE
00155 if (ret)
00156 qWarning("Mutex unlock failure: %s", strerror(ret));
00157 #endif
00158 }
00159
00160 bool QRealMutexPrivate::locked()
00161 {
00162 int ret = pthread_mutex_trylock(&handle);
00163
00164 if (ret == EBUSY) {
00165 return TRUE;
00166 } else if (ret) {
00167 #ifdef QT_CHECK_RANGE
00168 qWarning("Mutex locktest failure: %s", strerror(ret));
00169 #endif
00170 } else
00171 pthread_mutex_unlock(&handle);
00172
00173 return FALSE;
00174 }
00175
00176 bool QRealMutexPrivate::trylock()
00177 {
00178 int ret = pthread_mutex_trylock(&handle);
00179
00180 if (ret == EBUSY) {
00181 return FALSE;
00182 } else if (ret) {
00183 #ifdef QT_CHECK_RANGE
00184 qWarning("Mutex trylock failure: %s", strerror(ret));
00185 #endif
00186 return FALSE;
00187 }
00188
00189 return TRUE;
00190 }
00191
00192 int QRealMutexPrivate::type() const
00193 {
00194 return recursive ? Q_MUTEX_RECURSIVE : Q_MUTEX_NORMAL;
00195 }
00196
00197
00198 #ifndef Q_RECURSIVE_MUTEX_TYPE
00199 QRecursiveMutexPrivate::QRecursiveMutexPrivate()
00200 : count(0), owner(0)
00201 {
00202 pthread_mutexattr_t attr;
00203 pthread_mutexattr_init(&attr);
00204 Q_MUTEX_SET_TYPE(&attr, Q_NORMAL_MUTEX_TYPE);
00205 int ret = pthread_mutex_init(&handle, &attr);
00206 pthread_mutexattr_destroy(&attr);
00207
00208 # ifdef QT_CHECK_RANGE
00209 if (ret)
00210 qWarning( "Mutex init failure: %s", strerror(ret) );
00211 # endif
00212
00213 pthread_mutexattr_init(&attr);
00214 ret = pthread_mutex_init( &handle2, &attr );
00215 pthread_mutexattr_destroy(&attr);
00216
00217 # ifdef QT_CHECK_RANGE
00218 if (ret)
00219 qWarning( "Mutex init failure: %s", strerror(ret) );
00220 # endif
00221 }
00222
00223 QRecursiveMutexPrivate::~QRecursiveMutexPrivate()
00224 {
00225 int ret = pthread_mutex_destroy(&handle2);
00226
00227 # ifdef QT_CHECK_RANGE
00228 if (ret)
00229 qWarning( "Mutex destroy failure: %s", strerror(ret) );
00230 # endif
00231 }
00232
00233 void QRecursiveMutexPrivate::lock()
00234 {
00235 pthread_mutex_lock(&handle2);
00236
00237 if (count > 0 && owner == (unsigned long) pthread_self()) {
00238 count++;
00239 } else {
00240 pthread_mutex_unlock(&handle2);
00241 pthread_mutex_lock(&handle);
00242 pthread_mutex_lock(&handle2);
00243 count = 1;
00244 owner = (unsigned long) pthread_self();
00245 }
00246
00247 pthread_mutex_unlock(&handle2);
00248 }
00249
00250 void QRecursiveMutexPrivate::unlock()
00251 {
00252 pthread_mutex_lock(&handle2);
00253
00254 if (owner == (unsigned long) pthread_self()) {
00255
00256
00257 if (count && (--count) < 1) {
00258 count = 0;
00259 pthread_mutex_unlock(&handle);
00260 }
00261 } else {
00262 #ifdef QT_CHECK_RANGE
00263 qWarning("QMutex::unlock: unlock from different thread than locker");
00264 qWarning(" was locked by %d, unlock attempt from %d",
00265 (int)owner, (int)pthread_self());
00266 #endif
00267 }
00268
00269 pthread_mutex_unlock(&handle2);
00270 }
00271
00272 bool QRecursiveMutexPrivate::locked()
00273 {
00274 pthread_mutex_lock(&handle2);
00275
00276 bool ret;
00277 int code = pthread_mutex_trylock(&handle);
00278
00279 if (code == EBUSY) {
00280 ret = TRUE;
00281 } else {
00282 #ifdef QT_CHECK_RANGE
00283 if (code)
00284 qWarning("Mutex trylock failure: %s", strerror(code));
00285 #endif
00286
00287 pthread_mutex_unlock(&handle);
00288 ret = FALSE;
00289 }
00290
00291 pthread_mutex_unlock(&handle2);
00292
00293 return ret;
00294 }
00295
00296 bool QRecursiveMutexPrivate::trylock()
00297 {
00298 bool ret = TRUE;
00299
00300 pthread_mutex_lock(&handle2);
00301
00302 if ( count > 0 && owner == (unsigned long) pthread_self() ) {
00303 count++;
00304 } else {
00305 int code = pthread_mutex_trylock(&handle);
00306
00307 if (code == EBUSY) {
00308 ret = FALSE;
00309 } else if (code) {
00310 #ifdef QT_CHECK_RANGE
00311 qWarning("Mutex trylock failure: %s", strerror(code));
00312 #endif
00313 ret = FALSE;
00314 } else {
00315 count = 1;
00316 owner = (unsigned long) pthread_self();
00317 }
00318 }
00319
00320 pthread_mutex_unlock(&handle2);
00321
00322 return ret;
00323 }
00324
00325 int QRecursiveMutexPrivate::type() const
00326 {
00327 return Q_MUTEX_RECURSIVE;
00328 }
00329
00330 #endif // !Q_RECURSIVE_MUTEX_TYPE
00331
00332
00435 QMutex::QMutex(bool recursive)
00436 {
00437 #ifndef Q_RECURSIVE_MUTEX_TYPE
00438 if ( recursive )
00439 d = new QRecursiveMutexPrivate();
00440 else
00441 #endif // !Q_RECURSIVE_MUTEX_TYPE
00442 d = new QRealMutexPrivate(recursive);
00443 }
00444
00451 QMutex::~QMutex()
00452 {
00453 delete d;
00454 }
00455
00462 void QMutex::lock()
00463 {
00464 d->lock();
00465 }
00466
00475 void QMutex::unlock()
00476 {
00477 d->unlock();
00478 }
00479
00490 bool QMutex::locked()
00491 {
00492 return d->locked();
00493 }
00494
00506 bool QMutex::tryLock()
00507 {
00508 return d->trylock();
00509 }
00510
00689 #endif // QT_THREAD_SUPPORT