Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qmutex_unix.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** $Id: qmutex_unix.cpp,v 1.2 2003/07/10 02:40:12 llornkcor Exp $
00003 **
00004 ** QMutex class for Unix
00005 **
00006 ** Created : 20010725
00007 **
00008 ** Copyright (C) 1992-2002 Trolltech AS.  All rights reserved.
00009 **
00010 ** This file is part of the tools module of the Qt GUI Toolkit.
00011 **
00012 ** This file may be distributed under the terms of the Q Public License
00013 ** as defined by Trolltech AS of Norway and appearing in the file
00014 ** LICENSE.QPL included in the packaging of this file.
00015 **
00016 ** This file may be distributed and/or modified under the terms of the
00017 ** GNU General Public License version 2 as published by the Free Software
00018 ** Foundation and appearing in the file LICENSE.GPL included in the
00019 ** packaging of this file.
00020 **
00021 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
00022 ** licenses may use this file in accordance with the Qt Commercial License
00023 ** Agreement provided with the Software.
00024 **
00025 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00026 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00027 **
00028 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00029 **   information about Qt Commercial License Agreements.
00030 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00031 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00032 **
00033 ** Contact info@trolltech.com if any conditions of this licensing are
00034 ** not clear to you.
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 // POSIX threads mutex types
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 // POSIX 1003.1c-1995 - We love this OS
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 // POSIX 1003.4a pthreads draft extensions
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 // Unknown mutex types - skip them
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 // Private class declarations
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 // Private class implementation
00111 
00112 // base destructor
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 // real mutex class
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         // do nothing if the count is already 0... to reflect the behaviour described
00256         // in the docs
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

Generated on Sat Nov 5 16:18:31 2005 for OPIE by  doxygen 1.4.2