📄 qmutex_unix.cpp
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS. All rights reserved.**** This file is part of the Qtopia Environment.** ** This program is free software; you can redistribute it and/or modify it** under the terms of the GNU General Public License as published by the** Free Software Foundation; either version 2 of the License, or (at your** option) any later version.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** This program is distributed in the hope that it will be useful, but** WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU General Public License for more details.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#if defined(QT_THREAD_SUPPORT)#include "qplatformdefs.h"typedef pthread_mutex_t Q_MUTEX_T;// POSIX threads mutex types#if ((defined(PTHREAD_MUTEX_RECURSIVE) && defined(PTHREAD_MUTEX_DEFAULT)) || \ defined(Q_OS_FREEBSD)) && !defined(Q_OS_UNIXWARE) && !defined(Q_OS_SOLARIS) && \ !defined(Q_OS_MAC)// POSIX 1003.1c-1995 - We love this OS# define Q_MUTEX_SET_TYPE(a, b) pthread_mutexattr_settype((a), (b))# if defined(QT_CHECK_RANGE)# define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK# else# define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT# endif# define Q_RECURSIVE_MUTEX_TYPE PTHREAD_MUTEX_RECURSIVE#elif defined(MUTEX_NONRECURSIVE_NP) && defined(MUTEX_RECURSIVE_NP)// POSIX 1003.4a pthreads draft extensions# define Q_MUTEX_SET_TYPE(a, b) pthread_mutexattr_setkind_np((a), (b));# define Q_NORMAL_MUTEX_TYPE MUTEX_NONRECURSIVE_NP# define Q_RECURSIVE_MUTEX_TYPE MUTEX_RECURSIVE_NP#else// Unknown mutex types - skip them# define Q_MUTEX_SET_TYPE(a, b)# undef Q_NORMAL_MUTEX_TYPE# undef Q_RECURSIVE_MUTEX_TYPE#endif#include "qmutex.h"#include "qmutex_p.h"#include <errno.h>#include <string.h>// Private class declarationsclass QRealMutexPrivate : public QMutexPrivate {public: QRealMutexPrivate(bool = FALSE); void lock(); void unlock(); bool locked(); bool trylock(); int type() const; bool recursive;};#ifndef Q_RECURSIVE_MUTEX_TYPEclass QRecursiveMutexPrivate : public QMutexPrivate{public: QRecursiveMutexPrivate(); ~QRecursiveMutexPrivate(); void lock(); void unlock(); bool locked(); bool trylock(); int type() const; int count; unsigned long owner; pthread_mutex_t handle2;};#endif // !Q_RECURSIVE_MUTEX_TYPE// Private class implementation// base destructorQMutexPrivate::~QMutexPrivate(){ int ret = pthread_mutex_destroy(&handle);#ifdef QT_CHECK_RANGE if ( ret ) qWarning( "Mutex destroy failure: %s", strerror( ret ) );#endif}// real mutex classQRealMutexPrivate::QRealMutexPrivate(bool recurs) : recursive(recurs){ pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); Q_MUTEX_SET_TYPE(&attr, recursive ? Q_RECURSIVE_MUTEX_TYPE : Q_NORMAL_MUTEX_TYPE); Q_UNUSED(recursive); int ret = pthread_mutex_init(&handle, &attr); pthread_mutexattr_destroy(&attr);#ifdef QT_CHECK_RANGE if( ret ) qWarning( "Mutex init failure: %s", strerror( ret ) );#endif // QT_CHECK_RANGE}void QRealMutexPrivate::lock(){ int ret = pthread_mutex_lock(&handle);#ifdef QT_CHECK_RANGE if (ret) qWarning("Mutex lock failure: %s", strerror(ret));#endif}void QRealMutexPrivate::unlock(){ int ret = pthread_mutex_unlock(&handle);#ifdef QT_CHECK_RANGE if (ret) qWarning("Mutex unlock failure: %s", strerror(ret));#endif}bool QRealMutexPrivate::locked(){ int ret = pthread_mutex_trylock(&handle); if (ret == EBUSY) { return TRUE; } else if (ret) {#ifdef QT_CHECK_RANGE qWarning("Mutex locktest failure: %s", strerror(ret));#endif } else pthread_mutex_unlock(&handle); return FALSE;}bool QRealMutexPrivate::trylock(){ int ret = pthread_mutex_trylock(&handle); if (ret == EBUSY) { return FALSE; } else if (ret) {#ifdef QT_CHECK_RANGE qWarning("Mutex trylock failure: %s", strerror(ret));#endif return FALSE; } return TRUE;}int QRealMutexPrivate::type() const{ return recursive ? Q_MUTEX_RECURSIVE : Q_MUTEX_NORMAL;}#ifndef Q_RECURSIVE_MUTEX_TYPEQRecursiveMutexPrivate::QRecursiveMutexPrivate() : count(0), owner(0){ pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); Q_MUTEX_SET_TYPE(&attr, Q_NORMAL_MUTEX_TYPE); int ret = pthread_mutex_init(&handle, &attr); pthread_mutexattr_destroy(&attr);# ifdef QT_CHECK_RANGE if (ret) qWarning( "Mutex init failure: %s", strerror(ret) );# endif pthread_mutexattr_init(&attr); ret = pthread_mutex_init( &handle2, &attr ); pthread_mutexattr_destroy(&attr);# ifdef QT_CHECK_RANGE if (ret) qWarning( "Mutex init failure: %s", strerror(ret) );# endif}QRecursiveMutexPrivate::~QRecursiveMutexPrivate(){ int ret = pthread_mutex_destroy(&handle2);# ifdef QT_CHECK_RANGE if (ret) qWarning( "Mutex destroy failure: %s", strerror(ret) );# endif}void QRecursiveMutexPrivate::lock(){ pthread_mutex_lock(&handle2); if (count > 0 && owner == (unsigned long) pthread_self()) { count++; } else { pthread_mutex_unlock(&handle2); pthread_mutex_lock(&handle); pthread_mutex_lock(&handle2); count = 1; owner = (unsigned long) pthread_self(); } pthread_mutex_unlock(&handle2);}void QRecursiveMutexPrivate::unlock(){ pthread_mutex_lock(&handle2); if (owner == (unsigned long) pthread_self()) { // do nothing if the count is already 0... to reflect the behaviour described // in the docs if (count && (--count) < 1) { count = 0; pthread_mutex_unlock(&handle); } } else {#ifdef QT_CHECK_RANGE qWarning("QMutex::unlock: unlock from different thread than locker"); qWarning(" was locked by %d, unlock attempt from %d", (int)owner, (int)pthread_self());#endif } pthread_mutex_unlock(&handle2);}bool QRecursiveMutexPrivate::locked(){ pthread_mutex_lock(&handle2); bool ret; int code = pthread_mutex_trylock(&handle); if (code == EBUSY) { ret = TRUE; } else {#ifdef QT_CHECK_RANGE if (code) qWarning("Mutex trylock failure: %s", strerror(code));#endif pthread_mutex_unlock(&handle); ret = FALSE; } pthread_mutex_unlock(&handle2); return ret;}bool QRecursiveMutexPrivate::trylock(){ bool ret = TRUE; pthread_mutex_lock(&handle2); if ( count > 0 && owner == (unsigned long) pthread_self() ) { count++; } else { int code = pthread_mutex_trylock(&handle); if (code == EBUSY) { ret = FALSE; } else if (code) {#ifdef QT_CHECK_RANGE qWarning("Mutex trylock failure: %s", strerror(code));#endif ret = FALSE; } else { count = 1; owner = (unsigned long) pthread_self(); } } pthread_mutex_unlock(&handle2); return ret;}int QRecursiveMutexPrivate::type() const{ return Q_MUTEX_RECURSIVE;}#endif // !Q_RECURSIVE_MUTEX_TYPE/*! \class QMutex qmutex.h \threadsafe \brief The QMutex class provides access serialization between threads. \ingroup thread \ingroup environment The purpose of a QMutex is to protect an object, data structure or section of code so that only one thread can access it at a time (This is similar to the Java \c synchronized keyword). For example, say there is a method which prints a message to the user on two lines:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -