diff options
author | dimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7> | 2010-06-03 09:24:48 (GMT) |
---|---|---|
committer | dimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7> | 2010-06-03 09:24:48 (GMT) |
commit | 6d2875bda7b5416f2e8c72ec8677b7164de86187 (patch) | |
tree | 060dc6ccdb347682a1d4b73ab3098d95599532f2 /qtools | |
parent | 0fb3f32dfd7ac31a2677d76647700cd3fb730ef6 (diff) | |
download | Doxygen-6d2875bda7b5416f2e8c72ec8677b7164de86187.zip Doxygen-6d2875bda7b5416f2e8c72ec8677b7164de86187.tar.gz Doxygen-6d2875bda7b5416f2e8c72ec8677b7164de86187.tar.bz2 |
Release-1.6.3-20100603
Diffstat (limited to 'qtools')
-rw-r--r-- | qtools/Doxyfile | 8 | ||||
-rw-r--r-- | qtools/qgcache.cpp | 4 | ||||
-rw-r--r-- | qtools/qgdict.cpp | 8 | ||||
-rw-r--r-- | qtools/qmutex.cpp | 96 | ||||
-rw-r--r-- | qtools/qmutex.h | 83 | ||||
-rw-r--r-- | qtools/qmutex_p.h | 90 | ||||
-rw-r--r-- | qtools/qmutex_unix.cpp | 117 | ||||
-rw-r--r-- | qtools/qmutex_win32.cpp | 108 | ||||
-rw-r--r-- | qtools/qthread.cpp | 85 | ||||
-rw-r--r-- | qtools/qthread.h | 77 | ||||
-rw-r--r-- | qtools/qthread_p.h | 85 | ||||
-rw-r--r-- | qtools/qthread_unix.cpp | 218 | ||||
-rw-r--r-- | qtools/qthread_win32.cpp | 158 | ||||
-rw-r--r-- | qtools/qtools.pro.in | 22 | ||||
-rw-r--r-- | qtools/qwaitcondition.h | 68 | ||||
-rw-r--r-- | qtools/qwaitcondition_unix.cpp | 133 | ||||
-rw-r--r-- | qtools/qwaitcondition_win32.cpp | 186 | ||||
-rw-r--r-- | qtools/qxml.cpp | 4 |
18 files changed, 1535 insertions, 15 deletions
diff --git a/qtools/Doxyfile b/qtools/Doxyfile index 61f9093..bf28583 100644 --- a/qtools/Doxyfile +++ b/qtools/Doxyfile @@ -131,8 +131,8 @@ HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_COLORSTYLE_HUE = 220 -HTML_COLORSTYLE_SAT = 70 -HTML_COLORSTYLE_GAMMA = 60 +HTML_COLORSTYLE_SAT = 80 +HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = NO HTML_ALIGN_MEMBERS = YES HTML_DYNAMIC_SECTIONS = NO @@ -163,6 +163,7 @@ ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = YES USE_INLINE_TREES = NO TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 SEARCHENGINE = YES SERVER_BASED_SEARCH = NO @@ -244,7 +245,8 @@ CLASS_DIAGRAMS = YES MSCGEN_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = YES -DOT_FONTNAME = FreeSans +DOT_NUM_THREADS = 0 +DOT_FONTNAME = FreeSans.ttf DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = YES diff --git a/qtools/qgcache.cpp b/qtools/qgcache.cpp index 1fd876d..89282c7 100644 --- a/qtools/qgcache.cpp +++ b/qtools/qgcache.cpp @@ -630,7 +630,7 @@ void QGCache::statistics() const #if defined(DEBUG) QString line; line.fill( '*', 80 ); - qDebug( line.ascii() ); + qDebug( "%s",line.ascii() ); qDebug( "CACHE STATISTICS:" ); qDebug( "cache contains %d item%s, with a total cost of %d", count(), count() != 1 ? "s" : "", tCost ); @@ -651,7 +651,7 @@ void QGCache::statistics() const lruList->dumps != 1 ? "have" : "has", lruList->dumpCosts ); qDebug( "Statistics from internal dictionary class:" ); dict->statistics(); - qDebug( line.ascii() ); + qDebug( "%s",line.ascii() ); #endif } diff --git a/qtools/qgdict.cpp b/qtools/qgdict.cpp index e55d059..e51b9c1 100644 --- a/qtools/qgdict.cpp +++ b/qtools/qgdict.cpp @@ -907,11 +907,11 @@ void QGDict::statistics() const QString line; line.fill( '-', 60 ); double real, ideal; - qDebug( line.ascii() ); + qDebug( "%s",line.ascii() ); qDebug( "DICTIONARY STATISTICS:" ); if ( count() == 0 ) { qDebug( "Empty!" ); - qDebug( line.ascii() ); + qDebug( "%s", line.ascii() ); return; } real = 0.0; @@ -932,7 +932,7 @@ void QGDict::statistics() const while ( b-- ) *pbuf++ = '*'; *pbuf = '\0'; - qDebug( buf ); + qDebug( "%s", buf ); i++; } qDebug( "Array size = %d", size() ); @@ -940,7 +940,7 @@ void QGDict::statistics() const qDebug( "Real dist = %g", real ); qDebug( "Rand dist = %g", ideal ); qDebug( "Real/Rand = %g", real/ideal ); - qDebug( line.ascii() ); + qDebug( "%s",line.ascii() ); #endif // DEBUG } diff --git a/qtools/qmutex.cpp b/qtools/qmutex.cpp new file mode 100644 index 0000000..fda5f07 --- /dev/null +++ b/qtools/qmutex.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <stdio.h> + +#include "qglobal.h" + +#include "qmutex.h" +#include "qmutex_p.h" + +QMutex::QMutex() : d(new QMutexPrivate()) +{ +} + +QMutex::~QMutex() +{ + delete d; +} + +void QMutex::lock() +{ + //printf("%p: QMutex::lock(): enter\n",this); + bool isLocked; + isLocked = d->contenders == 0 && d->contenders.testAndSet(0, 1); + if (!isLocked) + { + isLocked = d->contenders.fetchAndAdd(1)==0; + if (!isLocked) + { + // didn't get the lock, wait for it + //printf("%p: QMutex::lock(): wait() %d\n",this,(int)d->contenders); + d->wait(); + + // release lock + d->contenders.fetchAndAdd(-1); + } + } + //printf("%p: QMutex::lock(): leave\n",this); +} + +bool QMutex::tryLock() +{ + bool isLocked = d->contenders == 0 && + d->contenders.testAndSet(0, 1); + return isLocked; +} + +void QMutex::unlock() +{ + //printf("%p: QMutex::unlock(): enter %d\n",this,(int)d->contenders); + if (!d->contenders.testAndSet(1, 0)) + { + //printf("%p: QMutex::unlock(): wakeUp()\n",this); + d->wakeUp(); + } + //printf("%p: QMutex::unlock(): leave\n",this); +} + diff --git a/qtools/qmutex.h b/qtools/qmutex.h new file mode 100644 index 0000000..d3d2ac0 --- /dev/null +++ b/qtools/qmutex.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMUTEX_H +#define QMUTEX_H + +#include "qglobal.h" + +class QMutexPrivate; + +class QMutex +{ +public: + QMutex(); + ~QMutex(); + + void lock(); + bool tryLock(); + void unlock(); + +private: + QMutex(const QMutex &); + QMutex &operator=(const QMutex &); + + QMutexPrivate *d; +}; + +class QMutexLocker +{ + public: + QMutexLocker(QMutex *m) : m_mutex(m) + { + m_mutex->lock(); + } + ~QMutexLocker() + { + m_mutex->unlock(); + } + QMutex *mutex() const { return m_mutex; } + + private: + QMutex *m_mutex; +}; + +#endif // QMUTEX_H diff --git a/qtools/qmutex_p.h b/qtools/qmutex_p.h new file mode 100644 index 0000000..a47b407 --- /dev/null +++ b/qtools/qmutex_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMUTEX_P_H +#define QMUTEX_P_H + +#include "qglobal.h" + +#if defined(_OS_UNIX_) || defined(_OS_MAC_) +#include <pthread.h> +#elif defined(_OS_WIN32_) +#include <windows.h> +#endif + +class QAtomicInt +{ + public: + QAtomicInt(int v=0) : m_value(v) {} + bool testAndSet(int expectedValue,int newValue); + int fetchAndAdd(int valueToAdd); + operator int () const { return m_value; } + bool operator==(int value) const { return m_value == value; } + bool operator!=(int value) const { return m_value != value; } + bool operator!() const { return m_value == 0; } + + private: + volatile int m_value; +}; + +class QMutexPrivate +{ +public: + QMutexPrivate(); + ~QMutexPrivate(); + + void wait(); + void wakeUp(); + + QAtomicInt contenders; + +#if defined(_OS_UNIX_) || defined(_OS_MAC_) + volatile bool wakeup; + pthread_mutex_t mutex; + pthread_cond_t cond; +#elif defined(_OS_WIN32_) + HANDLE event; +#else +#error "unsupported platform" +#endif +}; + +#endif // QMUTEX_P_H diff --git a/qtools/qmutex_unix.cpp b/qtools/qmutex_unix.cpp new file mode 100644 index 0000000..4fe9a58 --- /dev/null +++ b/qtools/qmutex_unix.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <errno.h> +#include <pthread.h> + +#include "qglobal.h" +#include "qmutex.h" +#include "qmutex_p.h" + +static pthread_mutex_t qAtomicMutex = PTHREAD_MUTEX_INITIALIZER; + +static void report_error(int code, const char *where, const char *what) +{ + if (code != 0) + qWarning("%s: %s failure: %d", where, what, code); +} + + +QMutexPrivate::QMutexPrivate() + : contenders(0), wakeup(FALSE) +{ + report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init"); + report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init"); +} + +QMutexPrivate::~QMutexPrivate() +{ + report_error(pthread_cond_destroy(&cond), "QMutex", "cv destroy"); + report_error(pthread_mutex_destroy(&mutex), "QMutex", "mutex destroy"); +} + +void QMutexPrivate::wait() +{ + report_error(pthread_mutex_lock(&mutex), "QMutex::lock", "mutex lock"); + int errorCode = 0; + while (!wakeup) + { + errorCode = pthread_cond_wait(&cond, &mutex); + if (errorCode) + { + report_error(errorCode, "QMutex::lock()", "cv wait"); + } + } + wakeup = FALSE; + report_error(pthread_mutex_unlock(&mutex), "QMutex::lock", "mutex unlock"); +} + +void QMutexPrivate::wakeUp() +{ + report_error(pthread_mutex_lock(&mutex), "QMutex::unlock", "mutex lock"); + wakeup = TRUE; + report_error(pthread_cond_signal(&cond), "QMutex::unlock", "cv signal"); + report_error(pthread_mutex_unlock(&mutex), "QMutex::unlock", "mutex unlock"); +} + +bool QAtomicInt::testAndSet(int expectedValue,int newValue) +{ + bool returnValue = false; + pthread_mutex_lock(&qAtomicMutex); + if (m_value == expectedValue) + { + m_value = newValue; + returnValue = true; + } + pthread_mutex_unlock(&qAtomicMutex); + return returnValue; +} + +int QAtomicInt::fetchAndAdd(int valueToAdd) +{ + int returnValue; + pthread_mutex_lock(&qAtomicMutex); + returnValue = m_value; + m_value += valueToAdd; + pthread_mutex_unlock(&qAtomicMutex); + return returnValue; +} + diff --git a/qtools/qmutex_win32.cpp b/qtools/qmutex_win32.cpp new file mode 100644 index 0000000..2d662ea --- /dev/null +++ b/qtools/qmutex_win32.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <windows.h> + +#include "qmutex.h" +#include "qmutex_p.h" + +QMutexPrivate::QMutexPrivate() + : contenders(0) +{ + event = CreateEvent(0, FALSE, FALSE, 0); + if (!event) + qWarning("QMutexPrivate::QMutexPrivate: Cannot create event"); +} + +QMutexPrivate::~QMutexPrivate() +{ + CloseHandle(event); +} + +void QMutexPrivate::wait() +{ + WaitForSingleObject(event, INFINITE); +} + +void QMutexPrivate::wakeUp() +{ + SetEvent(event); +} + +//---------------------------------------------------------------------- + +class QCriticalSection +{ + public: + QCriticalSection() { InitializeCriticalSection(§ion); } + ~QCriticalSection() { DeleteCriticalSection(§ion); } + void lock() { EnterCriticalSection(§ion); } + void unlock() { LeaveCriticalSection(§ion); } + + private: + CRITICAL_SECTION section; +}; + +static QCriticalSection qAtomicCriticalSection; + +bool QAtomicInt::testAndSet(int expectedValue,int newValue) +{ + bool returnValue = false; + qAtomicCriticalSection.lock(); + if (m_value == expectedValue) + { + m_value = newValue; + returnValue = true; + } + qAtomicCriticalSection.unlock(); + return returnValue; +} + +int QAtomicInt::fetchAndAdd(int valueToAdd) +{ + int returnValue; + qAtomicCriticalSection.lock(); + returnValue = m_value; + m_value += valueToAdd; + qAtomicCriticalSection.unlock(); + return returnValue; +} + diff --git a/qtools/qthread.cpp b/qtools/qthread.cpp new file mode 100644 index 0000000..db2a0de --- /dev/null +++ b/qtools/qthread.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qthread.h" +#include "qthread_p.h" + +QThread::QThread() + : d(new QThreadPrivate) +{ +} + +QThread::~QThread() +{ + QMutexLocker locker(&d->mutex); + if (d->running && !d->finished) + qWarning("QThread: Destroyed while thread is still running"); +} + +bool QThread::isFinished() const +{ + QMutexLocker locker(&d->mutex); + return d->finished; +} + +bool QThread::isRunning() const +{ + QMutexLocker locker(&d->mutex); + return d->running; +} + +void QThread::setStackSize(unsigned int stackSize) +{ + QMutexLocker locker(&d->mutex); + if (d->running) + { + qWarning("QThread: Cannot change stack size while thread is running!"); + return; + } + d->stackSize = stackSize; +} + +unsigned int QThread::stackSize() const +{ + QMutexLocker locker(&d->mutex); + return d->stackSize; +} + diff --git a/qtools/qthread.h b/qtools/qthread.h new file mode 100644 index 0000000..81868bd --- /dev/null +++ b/qtools/qthread.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTHREAD_H +#define QTHREAD_H + +class QThreadPrivate; + +class QThread +{ + public: + explicit QThread(); + virtual ~QThread(); + + bool isFinished() const; + bool isRunning() const; + + void start(); + void terminate(); + void wait(); + void setStackSize(unsigned int stackSize); + unsigned int stackSize() const; + static int idealThreadCount(); + +protected: + // events + virtual void started() {} + virtual void finished() {} + virtual void terminated() {} + + // main loop + virtual void run() {} + +private: + QThreadPrivate *d; + friend class QThreadPrivate; +}; + +#endif // QTHREAD_H diff --git a/qtools/qthread_p.h b/qtools/qthread_p.h new file mode 100644 index 0000000..87692aa --- /dev/null +++ b/qtools/qthread_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTHREAD_P_H +#define QTHREAD_P_H + +#include "qglobal.h" + +#if defined(_OS_UNIX_) || defined(_OS_MAC_) +#include <pthread.h> +#elif defined(_OS_WIN32_) +#include <windows.h> +#endif + +#include "qthread.h" +#include "qmutex.h" +#include "qwaitcondition.h" + +class QThreadPrivate +{ +public: + QThreadPrivate(); + ~QThreadPrivate(); + + mutable QMutex mutex; + + bool running; + bool finished; + bool terminated; + uint stackSize; + +#if defined(_OS_UNIX_) || defined(_OS_MAC_) + pthread_t thread_id; + QWaitCondition thread_done; + static void *start(void *arg); + static void finish(void *arg); +#elif defined(_OS_WIN32_) + HANDLE handle; + static unsigned int __stdcall start(void *); + static void finish(void *,bool lockAnyway=TRUE); + int waiters; +#else +#error "unsupported platform!" +#endif +}; + +#endif // QTHREAD_P_H diff --git a/qtools/qthread_unix.cpp b/qtools/qthread_unix.cpp new file mode 100644 index 0000000..53242cc --- /dev/null +++ b/qtools/qthread_unix.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglobal.h" + +#if defined(_OS_HPUX_) +#include <sys/pstat.h> +#elif defined(_OS_MAC_) +#undef DEBUG +#include <CoreServices/CoreServices.h> +#elif defined(_OS_BSDI_) +#include <mach/mach_types.h> +#include <sys/systm.h> +#include <sys/types.h> +#include <sys/sysctl.h> +#endif +#include <unistd.h> + +#include "qthread.h" +#include "qthread_p.h" + + +/************************************************************************** + ** QThreadPrivate + *************************************************************************/ + +QThreadPrivate::QThreadPrivate() : + running(FALSE), finished(FALSE), terminated(FALSE), stackSize(0) +{ + thread_id = 0; +} + +QThreadPrivate::~QThreadPrivate() +{ +} + +void *QThreadPrivate::start(void *arg) +{ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + pthread_cleanup_push(QThreadPrivate::finish, arg); + + QThread *thr = reinterpret_cast<QThread *>(arg); + + thr->started(); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_testcancel(); + thr->run(); + + pthread_cleanup_pop(1); + return 0; +} + +void QThreadPrivate::finish(void *arg) +{ + QThread *thr = reinterpret_cast<QThread *>(arg); + QThreadPrivate *d = thr->d; + QMutexLocker locker(&d->mutex); + + d->running = FALSE; + d->finished = TRUE; + if (d->terminated) + thr->terminated(); + d->terminated = FALSE; + thr->finished(); + + d->thread_id = 0; + d->thread_done.wakeAll(); +} + + + + +/************************************************************************** + ** QThread + *************************************************************************/ + +void QThread::start() +{ + QMutexLocker locker(&d->mutex); + if (d->running) return; + + d->running = TRUE; + d->finished = FALSE; + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); + pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); + if (d->stackSize>0) + { +#if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0>0) + pthread_attr_setstacksize(&attr,d->stackSize); +#endif + } + int code = pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this); + pthread_attr_destroy(&attr); + + if (code) + { + qWarning("QThread::start: Thread creation error: %d", code); + + d->running = FALSE; + d->finished = FALSE; + d->thread_id = 0; + } +} + +void QThread::terminate() +{ + QMutexLocker locker(&d->mutex); + + if (!d->thread_id) return; + + int code = pthread_cancel(d->thread_id); + if (code) + { + qWarning("QThread::start: Thread termination error: %d", code); + } + else + { + d->terminated = TRUE; + } +} + +void QThread::wait() +{ + QMutexLocker locker(&d->mutex); + if (d->finished || !d->running) return; + + while (d->running) + { + d->thread_done.wait(locker.mutex()); + } +} + +#if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN) +// LSB doesn't define _SC_NPROCESSORS_ONLN. +# define _SC_NPROCESSORS_ONLN 84 +#endif + +int QThread::idealThreadCount() +{ + int cores = -1; +#if defined(_OS_MAC_) + // Mac OS X + cores = MPProcessorsScheduled(); +#elif defined(_OS_HPUX_) + // HP-UX + struct pst_dynamic psd; + if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) == -1) + { + perror("pstat_getdynamic"); + cores = -1; + } + else + { + cores = (int)psd.psd_proc_cnt; + } +#elif defined(_OS_BSDI_) + // FreeBSD, OpenBSD, NetBSD, BSD/OS + size_t len = sizeof(cores); + int mib[2]; + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + + if (sysctl(mib, 2, &cores, &len, NULL, 0) != 0) + { + perror("sysctl"); + cores = -1; + } +#elif defined(_OS_IRIX_) + // IRIX + cores = (int)sysconf(_SC_NPROC_ONLN); +#else + // the rest: Linux, Solaris, AIX, Tru64 + cores = (int)sysconf(_SC_NPROCESSORS_ONLN); +#endif + return cores; +} + diff --git a/qtools/qthread_win32.cpp b/qtools/qthread_win32.cpp new file mode 100644 index 0000000..2c62e93 --- /dev/null +++ b/qtools/qthread_win32.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qthread.h" +#include "qthread_p.h" + +/************************************************************************** + ** QThreadPrivate + *************************************************************************/ + +QThreadPrivate::QThreadPrivate() : + running(FALSE), finished(FALSE), terminated(FALSE), stackSize(0) +{ + handle = NULL; + waiters = 0; +} + +QThreadPrivate::~QThreadPrivate() +{ +} + +unsigned int __stdcall QThreadPrivate::start(void *arg) +{ + QThread *thr = reinterpret_cast<QThread *>(arg); + thr->started(); + thr->run(); + finish(arg); + return 0; +} + +void QThreadPrivate::finish(void *arg,bool lockAnyway) +{ + QThread *thr = reinterpret_cast<QThread *>(arg); + QThreadPrivate *d = thr->d; + + if (lockAnyway) d->mutex.lock(); + + d->running = FALSE; + d->finished = TRUE; + if (d->terminated) thr->terminated(); + d->terminated = FALSE; + thr->finished(); + + if (!d->waiters) + { + CloseHandle(d->handle); + d->handle = 0; + } + + if (lockAnyway) d->mutex.unlock(); +} + +/************************************************************************** + ** QThread + *************************************************************************/ + +void QThread::start() +{ + QMutexLocker locker(&d->mutex); + + if (d->running) return; + + d->running = TRUE; + d->finished = FALSE; + d->terminated = FALSE; + + d->handle = CreateThread(NULL,d->stackSize, + (LPTHREAD_START_ROUTINE)QThreadPrivate::start,this,0,NULL); + + if (!d->handle) + { + qWarning("QThread::start: Failed to create thread: errno=%d",errno); + d->running = FALSE; + d->finished = TRUE; + return; + } +} + +void QThread::terminate() +{ + QMutexLocker locker(&d->mutex); + if (!d->running) return; + TerminateThread(d->handle, 0); + d->terminated = TRUE; + QThreadPrivate::finish(this); +} + +void QThread::wait() +{ + QMutexLocker locker(&d->mutex); + if (d->finished || !d->running) return; + + ++d->waiters; + locker.mutex()->unlock(); + + WaitForSingleObject(d->handle,INFINITE); + + locker.mutex()->lock(); + --d->waiters; + if (!d->finished) // thread was terminated by someone else + { + d->terminated = TRUE; + QThreadPrivate::finish(this); + } + + if (d->finished && d->waiters) + { + CloseHandle(d->handle); + d->handle = 0; + } +} + +int QThread::idealThreadCount() +{ + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + return sysinfo.dwNumberOfProcessors; +} + + diff --git a/qtools/qtools.pro.in b/qtools/qtools.pro.in index d2550f6..f0a1ffa 100644 --- a/qtools/qtools.pro.in +++ b/qtools/qtools.pro.in @@ -44,7 +44,13 @@ HEADERS = qarray.h \ qxml.h \ qvaluestack.h \ qmap.h \ - qmodules.h + qmodules.h \ + qthread.h \ + qthread_p.h \ + qmutex.h \ + qmutex_p.h \ + qwaitcondition.h + SOURCES = qbuffer.cpp \ qcollection.cpp \ scstring.cpp \ @@ -67,15 +73,23 @@ SOURCES = qbuffer.cpp \ qtextcodec.cpp \ qstringlist.cpp \ qxml.cpp \ - qmap.cpp + qmap.cpp \ + qthread.cpp \ + qmutex.cpp unix:SOURCES += qfile_unix.cpp \ qdir_unix.cpp \ - qfileinfo_unix.cpp + qfileinfo_unix.cpp \ + qthread_unix.cpp \ + qmutex_unix.cpp \ + qwaitcondition_unix.cpp win32:SOURCES += qfile_win32.cpp \ qdir_win32.cpp \ - qfileinfo_win32.cpp + qfileinfo_win32.cpp \ + qthread_win32.cpp \ + qmutex_win32.cpp \ + qwaitcondition_win32.cpp INCLUDEPATH = . TMAKE_CXXFLAGS += -DQT_NO_CODECS -DQT_LITE_UNICODE diff --git a/qtools/qwaitcondition.h b/qtools/qwaitcondition.h new file mode 100644 index 0000000..4d5b3bd --- /dev/null +++ b/qtools/qwaitcondition.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAITCONDITION_H +#define QWAITCONDITION_H + +#include "qglobal.h" + +class QWaitConditionPrivate; +class QMutex; + +class QWaitCondition +{ +public: + QWaitCondition(); + ~QWaitCondition(); + + void wait(QMutex *mutex); + + void wakeOne(); + void wakeAll(); + +private: + QWaitCondition(const QWaitCondition &); + QWaitCondition &operator=(const QWaitCondition &); + + QWaitConditionPrivate * d; +}; + +#endif // QWAITCONDITION_H diff --git a/qtools/qwaitcondition_unix.cpp b/qtools/qwaitcondition_unix.cpp new file mode 100644 index 0000000..aa22a4b --- /dev/null +++ b/qtools/qwaitcondition_unix.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaitcondition.h" +#include "qmutex.h" +#include <pthread.h> + +#define MIN(a,b) ((a)<(b)?(a):(b)) + +static void report_error(int code, const char *where, const char *what) +{ + if (code != 0) + qWarning("%s: %s failure: %d", where, what, code); +} + +struct QWaitConditionPrivate +{ + pthread_mutex_t mutex; + pthread_cond_t cond; + int waiters; + int wakeups; + + void wait() + { + int code; + for (;;) + { + code = pthread_cond_wait(&cond, &mutex); + if (code == 0 && wakeups == 0) + { + // many vendors warn of spurios wakeups from + // pthread_cond_wait(), especially after signal delivery, + // even though POSIX doesn't allow for it... sigh + continue; + } + break; + } + + --waiters; + if (code == 0) + { + --wakeups; + } + else + { + report_error(code, "QWaitCondition::wait()", "cv wait"); + } + report_error(pthread_mutex_unlock(&mutex), "QWaitCondition::wait()", "mutex unlock"); + } +}; + + +QWaitCondition::QWaitCondition() +{ + d = new QWaitConditionPrivate; + report_error(pthread_mutex_init(&d->mutex, NULL), "QWaitCondition", "mutex init"); + report_error(pthread_cond_init(&d->cond, NULL), "QWaitCondition", "cv init"); + d->waiters = d->wakeups = 0; +} + + +QWaitCondition::~QWaitCondition() +{ + report_error(pthread_cond_destroy(&d->cond), "QWaitCondition", "cv destroy"); + report_error(pthread_mutex_destroy(&d->mutex), "QWaitCondition", "mutex destroy"); + delete d; +} + +void QWaitCondition::wakeOne() +{ + report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wakeOne()", "mutex lock"); + d->wakeups = MIN(d->wakeups + 1, d->waiters); + report_error(pthread_cond_signal(&d->cond), "QWaitCondition::wakeOne()", "cv signal"); + report_error(pthread_mutex_unlock(&d->mutex), "QWaitCondition::wakeOne()", "mutex unlock"); +} + +void QWaitCondition::wakeAll() +{ + report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wakeAll()", "mutex lock"); + d->wakeups = d->waiters; + report_error(pthread_cond_broadcast(&d->cond), "QWaitCondition::wakeAll()", "cv broadcast"); + report_error(pthread_mutex_unlock(&d->mutex), "QWaitCondition::wakeAll()", "mutex unlock"); +} + +void QWaitCondition::wait(QMutex *mutex) +{ + if (!mutex) return; + + report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock"); + ++d->waiters; + mutex->unlock(); + d->wait(); + mutex->lock(); +} + diff --git a/qtools/qwaitcondition_win32.cpp b/qtools/qwaitcondition_win32.cpp new file mode 100644 index 0000000..77eb039 --- /dev/null +++ b/qtools/qwaitcondition_win32.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <windows.h> +#include "qwaitcondition.h" +#include "qmutex.h" +#include "qlist.h" + +//*********************************************************************** +// QWaitConditionPrivate +// ********************************************************************** + +class QWaitConditionEvent +{ +public: + QWaitConditionEvent() : priority(0), wokenUp(false) + { + event = CreateEvent(NULL, TRUE, FALSE, NULL); + } + ~QWaitConditionEvent() { CloseHandle(event); } + int priority; + bool wokenUp; + HANDLE event; +}; + +class EventQueue : public QList<QWaitConditionEvent> +{ + public: + EventQueue() { setAutoDelete(TRUE); } + ~EventQueue() {} +}; + +class QWaitConditionPrivate +{ +public: + QMutex mtx; + EventQueue queue; + EventQueue freeQueue; + + QWaitConditionEvent *pre(); + void wait(QWaitConditionEvent *wce); + void post(QWaitConditionEvent *wce); +}; + +QWaitConditionEvent *QWaitConditionPrivate::pre() +{ + mtx.lock(); + QWaitConditionEvent *wce = + freeQueue.isEmpty() ? new QWaitConditionEvent : freeQueue.take(0); + wce->priority = GetThreadPriority(GetCurrentThread()); + wce->wokenUp = FALSE; + + // insert 'wce' into the queue (sorted by priority) + uint index = 0; + for (; index < queue.count(); ++index) + { + QWaitConditionEvent *current = queue.at(index); + if (current->priority < wce->priority) + break; + } + queue.insert(index, wce); + mtx.unlock(); + + return wce; +} + +void QWaitConditionPrivate::wait(QWaitConditionEvent *wce) +{ + WaitForSingleObject(wce->event, INFINITE); +} + +void QWaitConditionPrivate::post(QWaitConditionEvent *wce) +{ + mtx.lock(); + + // remove 'wce' from the queue + int idx = queue.find(wce); + ASSERT(idx!=-1); + queue.take(idx); + ResetEvent(wce->event); + freeQueue.append(wce); + + // wakeups delivered after the timeout should be forwarded to the next waiter + if (wce->wokenUp && !queue.isEmpty()) + { + QWaitConditionEvent *other = queue.getFirst(); + SetEvent(other->event); + other->wokenUp = TRUE; + } + + mtx.unlock(); +} + +//*********************************************************************** +// QWaitCondition implementation +//*********************************************************************** + +QWaitCondition::QWaitCondition() +{ + d = new QWaitConditionPrivate; +} + +QWaitCondition::~QWaitCondition() +{ + if (!d->queue.isEmpty()) + { + qWarning("QWaitCondition: Destroyed while threads are still waiting"); + } + delete d; +} + +void QWaitCondition::wait(QMutex *mutex) +{ + if (!mutex) return; + + QWaitConditionEvent *wce = d->pre(); + mutex->unlock(); + d->wait(wce); + mutex->lock(); + d->post(wce); +} + +void QWaitCondition::wakeOne() +{ + // wake up the first waiting thread in the queue + QMutexLocker locker(&d->mtx); + for (uint i = 0; i < d->queue.count(); ++i) + { + QWaitConditionEvent *current = d->queue.at(i); + if (current->wokenUp) continue; + SetEvent(current->event); + current->wokenUp = TRUE; + break; + } +} + +void QWaitCondition::wakeAll() +{ + // wake up the all threads in the queue + QMutexLocker locker(&d->mtx); + for (uint i = 0; i < d->queue.count(); ++i) + { + QWaitConditionEvent *current = d->queue.at(i); + SetEvent(current->event); + current->wokenUp = TRUE; + } +} + diff --git a/qtools/qxml.cpp b/qtools/qxml.cpp index c05ab88..9a24c1b 100644 --- a/qtools/qxml.cpp +++ b/qtools/qxml.cpp @@ -1944,7 +1944,7 @@ bool QXmlSimpleReader::feature( const QString& name, bool *ok ) const } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) { return d->reportWhitespaceCharData; } else { - qWarning( "Unknown feature " + name ); + qWarning( "Unknown feature %s", name.ascii() ); if ( ok != 0 ) *ok = FALSE; } @@ -1978,7 +1978,7 @@ void QXmlSimpleReader::setFeature( const QString& name, bool value ) } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) { d->reportWhitespaceCharData = value; } else { - qWarning( "Unknown feature " + name ); + qWarning( "Unknown feature %s", name.ascii() ); } } |