diff options
Diffstat (limited to 'src/corelib/thread')
37 files changed, 1586 insertions, 110 deletions
diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp index c2c9484cf6..5443d6e1b6 100644 --- a/src/corelib/thread/qatomic.cpp +++ b/src/corelib/thread/qatomic.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h index 07350ecfcd..b75ae94429 100644 --- a/src/corelib/thread/qatomic.h +++ b/src/corelib/thread/qatomic.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -44,13 +44,12 @@ #ifndef QATOMIC_H #define QATOMIC_H -#include <QtCore/qoldbasicatomic.h> +#include <QtCore/qbasicatomic.h> QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -QT_MODULE(Core) #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) # pragma GCC diagnostic push diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h new file mode 100644 index 0000000000..47d690c13f --- /dev/null +++ b/src/corelib/thread/qbasicatomic.h @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBASICATOMIC_H +#define QBASICATOMIC_H + +#include <QtCore/qglobal.h> + +#if defined(QT_MOC) || defined(QT_BUILD_QMAKE) || defined(QT_RCC) || defined(QT_UIC) || defined(QT_BOOTSTRAPPED) +# include <QtCore/qatomic_bootstrap.h> +#elif defined(Q_CC_MSVC) +# include <QtCore/qatomic_msvc.h> +#elif defined(__arm__) || defined(__TARGET_ARCH_ARM) +# include <QtCore/qatomic_arm.h> +#elif defined(__i386) || defined(__i386__) +# include <QtCore/qatomic_i386.h> +#elif defined(__ia64) || defined(__ia64__) +# include "QtCore/qatomic_ia64.h" +#elif defined(__mips) || defined(__mips__) +# include "QtCore/qatomic_mips.h" +#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) +# include <QtCore/qatomic_x86_64.h> +#elif defined(Q_COMPILER_ATOMICS) && defined(Q_COMPILER_CONSTEXPR) +# include <QtCore/qatomic_cxx11.h> +#elif defined(Q_CC_GNU) +# include <QtCore/qatomic_gcc.h> +#else +# define QT_OLD_ATOMICS +#endif + +#ifdef QT_OLD_ATOMICS +# include "QtCore/qoldbasicatomic.h" +# undef QT_OLD_ATOMICS +#else + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +#if 0 +#pragma qt_no_master_include +#pragma qt_sync_stop_processing +#endif + +// New atomics + +template <typename T> +class QBasicAtomicInteger +{ +public: + typedef QAtomicOps<T> Ops; + // static check that this is a valid integer + typedef char PermittedIntegerType[QAtomicIntegerTraits<T>::IsInteger ? 1 : -1]; + + typename Ops::Type _q_value; + + // Non-atomic API + T load() const { return Ops::load(_q_value); } + void store(T newValue) { Ops::store(_q_value, newValue); } + + // Atomic API, implemented in qatomic_XXX.h + + T loadAcquire() { return Ops::loadAcquire(_q_value); } + void storeRelease(T newValue) { Ops::storeRelease(_q_value, newValue); } + + static bool isReferenceCountingNative() { return Ops::isReferenceCountingNative(); } + static bool isReferenceCountingWaitFree() { return Ops::isReferenceCountingWaitFree(); } + + bool ref() { return Ops::ref(_q_value); } + bool deref() { return Ops::deref(_q_value); } + + static bool isTestAndSetNative() { return Ops::isTestAndSetNative(); } + static bool isTestAndSetWaitFree() { return Ops::isTestAndSetWaitFree(); } + + bool testAndSetRelaxed(T expectedValue, T newValue) + { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); } + bool testAndSetAcquire(T expectedValue, T newValue) + { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); } + bool testAndSetRelease(T expectedValue, T newValue) + { return Ops::testAndSetRelease(_q_value, expectedValue, newValue); } + bool testAndSetOrdered(T expectedValue, T newValue) + { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); } + + static bool isFetchAndStoreNative() { return Ops::isFetchAndStoreNative(); } + static bool isFetchAndStoreWaitFree() { return Ops::isFetchAndStoreWaitFree(); } + + T fetchAndStoreRelaxed(T newValue) + { return Ops::fetchAndStoreRelaxed(_q_value, newValue); } + T fetchAndStoreAcquire(T newValue) + { return Ops::fetchAndStoreAcquire(_q_value, newValue); } + T fetchAndStoreRelease(T newValue) + { return Ops::fetchAndStoreRelease(_q_value, newValue); } + T fetchAndStoreOrdered(T newValue) + { return Ops::fetchAndStoreOrdered(_q_value, newValue); } + + static bool isFetchAndAddNative() { return Ops::isFetchAndAddNative(); } + static bool isFetchAndAddWaitFree() { return Ops::isFetchAndAddWaitFree(); } + + T fetchAndAddRelaxed(T valueToAdd) + { return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); } + T fetchAndAddAcquire(T valueToAdd) + { return Ops::fetchAndAddAcquire(_q_value, valueToAdd); } + T fetchAndAddRelease(T valueToAdd) + { return Ops::fetchAndAddRelease(_q_value, valueToAdd); } + T fetchAndAddOrdered(T valueToAdd) + { return Ops::fetchAndAddOrdered(_q_value, valueToAdd); } + +#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_DELETE_MEMBERS) + QBasicAtomicInteger() = default; + constexpr QBasicAtomicInteger(T value) : _q_value(value) {} + QBasicAtomicInteger(const QBasicAtomicInteger &) = delete; + QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) = delete; + QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) volatile = delete; +#endif +}; +typedef QBasicAtomicInteger<int> QBasicAtomicInt; + +template <typename X> +class QBasicAtomicPointer +{ +public: + typedef X *Type; + typedef QAtomicOps<Type> Ops; + typedef typename Ops::Type AtomicType; + + AtomicType _q_value; + + // Non-atomic API + Type load() const { return _q_value; } + void store(Type newValue) { _q_value = newValue; } + + // Atomic API, implemented in qatomic_XXX.h + Type loadAcquire() { return Ops::loadAcquire(_q_value); } + void storeRelease(Type newValue) { Ops::storeRelease(_q_value, newValue); } + + static bool isTestAndSetNative() { return Ops::isTestAndSetNative(); } + static bool isTestAndSetWaitFree() { return Ops::isTestAndSetWaitFree(); } + + bool testAndSetRelaxed(Type expectedValue, Type newValue) + { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); } + bool testAndSetAcquire(Type expectedValue, Type newValue) + { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); } + bool testAndSetRelease(Type expectedValue, Type newValue) + { return Ops::testAndSetRelease(_q_value, expectedValue, newValue); } + bool testAndSetOrdered(Type expectedValue, Type newValue) + { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); } + + static bool isFetchAndStoreNative() { return Ops::isFetchAndStoreNative(); } + static bool isFetchAndStoreWaitFree() { return Ops::isFetchAndStoreWaitFree(); } + + Type fetchAndStoreRelaxed(Type newValue) + { return Ops::fetchAndStoreRelaxed(_q_value, newValue); } + Type fetchAndStoreAcquire(Type newValue) + { return Ops::fetchAndStoreAcquire(_q_value, newValue); } + Type fetchAndStoreRelease(Type newValue) + { return Ops::fetchAndStoreRelease(_q_value, newValue); } + Type fetchAndStoreOrdered(Type newValue) + { return Ops::fetchAndStoreOrdered(_q_value, newValue); } + + static bool isFetchAndAddNative() { return Ops::isFetchAndAddNative(); } + static bool isFetchAndAddWaitFree() { return Ops::isFetchAndAddWaitFree(); } + + Type fetchAndAddRelaxed(qptrdiff valueToAdd) + { return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); } + Type fetchAndAddAcquire(qptrdiff valueToAdd) + { return Ops::fetchAndAddAcquire(_q_value, valueToAdd); } + Type fetchAndAddRelease(qptrdiff valueToAdd) + { return Ops::fetchAndAddRelease(_q_value, valueToAdd); } + Type fetchAndAddOrdered(qptrdiff valueToAdd) + { return Ops::fetchAndAddOrdered(_q_value, valueToAdd); } + +#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_DELETE_MEMBERS) + QBasicAtomicPointer() = default; + constexpr QBasicAtomicPointer(Type value) : _q_value(value) {} + QBasicAtomicPointer(const QBasicAtomicPointer &) = delete; + QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) = delete; + QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) volatile = delete; +#endif +}; + +#ifndef Q_BASIC_ATOMIC_INITIALIZER +# define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) } +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QT_OLD_ATOMICS + + +#endif // QBASIC_ATOMIC diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h new file mode 100644 index 0000000000..984ebed47b --- /dev/null +++ b/src/corelib/thread/qgenericatomic.h @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGENERICATOMIC_H +#define QGENERICATOMIC_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#if 0 +#pragma qt_sync_stop_processing +#endif + +#ifdef Q_CC_GNU +// lowercase is fine, we'll undef it below +#define always_inline __attribute__((always_inline, gnu_inline)) +#else +#define always_inline +#endif + +template<typename T> struct QAtomicIntegerTraits { enum { IsInteger = 0 }; }; + +template <typename T> struct QAtomicAdditiveType +{ + typedef T AdditiveT; + static const int AddScale = 1; +}; +template <typename T> struct QAtomicAdditiveType<T *> +{ + typedef qptrdiff AdditiveT; + static const int AddScale = sizeof(T); +}; + +// not really atomic... +template <typename BaseClass> struct QGenericAtomicOps +{ + template <typename T> struct AtomicType { typedef T Type; typedef T *PointerType; }; + + static void acquireMemoryFence() { BaseClass::orderedMemoryFence(); } + static void releaseMemoryFence() { BaseClass::orderedMemoryFence(); } + static void orderedMemoryFence() { } + + template <typename T> static inline always_inline + T load(T &_q_value) + { + return _q_value; + } + + template <typename T, typename X> static inline always_inline + void store(T &_q_value, X newValue) + { + _q_value = newValue; + } + + template <typename T> static inline always_inline + T loadAcquire(T &_q_value) + { + T tmp = *static_cast<volatile T *>(&_q_value); + BaseClass::acquireMemoryFence(); + return tmp; + } + + template <typename T, typename X> static inline always_inline + void storeRelease(T &_q_value, X newValue) + { + BaseClass::releaseMemoryFence(); + *static_cast<volatile T *>(&_q_value) = newValue; + } + + static inline bool isReferenceCountingNative() + { return BaseClass::isFetchAndAddNative(); } + static inline bool isReferenceCountingWaitFree() + { return BaseClass::isFetchAndAddWaitFree(); } + template <typename T> static inline always_inline + bool ref(T &_q_value) + { + return BaseClass::fetchAndAddRelaxed(_q_value, 1) != T(-1); + } + + template <typename T> static inline always_inline + bool deref(T &_q_value) + { + return BaseClass::fetchAndAddRelaxed(_q_value, -1) != 1; + } + +#if 0 + // These functions have no default implementation + // Archictectures must implement them + static inline bool isTestAndSetNative(); + static inline bool isTestAndSetWaitFree(); + template <typename T, typename X> static inline + bool testAndSetRelaxed(T &_q_value, X expectedValue, X newValue); +#endif + + template <typename T, typename X> static inline always_inline + bool testAndSetAcquire(T &_q_value, X expectedValue, X newValue) + { + bool tmp = BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue); + BaseClass::acquireMemoryFence(); + return tmp; + } + + template <typename T, typename X> static inline always_inline + bool testAndSetRelease(T &_q_value, X expectedValue, X newValue) + { + BaseClass::releaseMemoryFence(); + return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue); + } + + template <typename T, typename X> static inline always_inline + bool testAndSetOrdered(T &_q_value, X expectedValue, X newValue) + { + BaseClass::orderedMemoryFence(); + return BaseClass::testAndSetRelaxed(_q_value, expectedValue, newValue); + } + + static inline bool isFetchAndStoreNative() { return false; } + static inline bool isFetchAndStoreWaitFree() { return false; } + + template <typename T, typename X> static inline always_inline + T fetchAndStoreRelaxed(T &_q_value, X newValue) + { + // implement fetchAndStore on top of testAndSet + Q_FOREVER { + register T tmp = load(_q_value); + if (BaseClass::testAndSetRelaxed(_q_value, tmp, newValue)) + return tmp; + } + } + + template <typename T, typename X> static inline always_inline + T fetchAndStoreAcquire(T &_q_value, X newValue) + { + T tmp = BaseClass::fetchAndStoreRelaxed(_q_value, newValue); + BaseClass::acquireMemoryFence(); + return tmp; + } + + template <typename T, typename X> static inline always_inline + T fetchAndStoreRelease(T &_q_value, X newValue) + { + BaseClass::releaseMemoryFence(); + return BaseClass::fetchAndStoreRelaxed(_q_value, newValue); + } + + template <typename T, typename X> static inline always_inline + T fetchAndStoreOrdered(T &_q_value, X newValue) + { + BaseClass::orderedMemoryFence(); + return BaseClass::fetchAndStoreRelaxed(_q_value, newValue); + } + + static inline bool isFetchAndAddNative() { return false; } + static inline bool isFetchAndAddWaitFree() { return false; } + template <typename T> static inline always_inline + T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) + { + // implement fetchAndAdd on top of testAndSet + Q_FOREVER { + register T tmp = BaseClass::load(_q_value); + if (BaseClass::testAndSetRelaxed(_q_value, tmp, T(tmp + valueToAdd))) + return tmp; + } + } + + template <typename T> static inline always_inline + T fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) + { + T tmp = BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd); + BaseClass::acquireMemoryFence(); + return tmp; + } + + template <typename T> static inline always_inline + T fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) + { + BaseClass::releaseMemoryFence(); + return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd); + } + + template <typename T> static inline always_inline + T fetchAndAddOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) + { + BaseClass::orderedMemoryFence(); + return BaseClass::fetchAndAddRelaxed(_q_value, valueToAdd); + } +}; + +#undef always_inline + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // QGENERICATOMIC_H diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 6c8ed3b897..4a64feff0e 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 1d7e591b7d..9a81b3d4bd 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -50,7 +50,6 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -QT_MODULE(Core) #if !defined(QT_NO_THREAD) && !defined(qdoc) diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp index 9bb9c9061e..b1618f7fc9 100644 --- a/src/corelib/thread/qmutex_linux.cpp +++ b/src/corelib/thread/qmutex_linux.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qmutex_mac.cpp b/src/corelib/thread/qmutex_mac.cpp index 1a561aa5d5..ecd3442d91 100644 --- a/src/corelib/thread/qmutex_mac.cpp +++ b/src/corelib/thread/qmutex_mac.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h index 0cbc99adc6..3cf0938e94 100644 --- a/src/corelib/thread/qmutex_p.h +++ b/src/corelib/thread/qmutex_p.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -118,8 +118,8 @@ public: bool wakeup; pthread_mutex_t mutex; pthread_cond_t cond; -#elif defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - HANDLE event; +#elif defined(Q_OS_WIN) + Qt::HANDLE event; #endif }; #endif //Q_OS_LINUX diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index a426d958f2..0347d4b3da 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index b513b6e1ad..1fdf97b0d0 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,15 +34,15 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include <qt_windows.h> - #include "qmutex.h" #include <qatomic.h> #include "qmutex_p.h" +#include <qt_windows.h> QT_BEGIN_NAMESPACE diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp index 6be5e092d7..b102770d23 100644 --- a/src/corelib/thread/qmutexpool.cpp +++ b/src/corelib/thread/qmutexpool.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h index 90b89f9a17..ce55a40bb8 100644 --- a/src/corelib/thread/qmutexpool_p.h +++ b/src/corelib/thread/qmutexpool_p.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qoldbasicatomic.h b/src/corelib/thread/qoldbasicatomic.h index 2f952c9e0a..a1985793ed 100644 --- a/src/corelib/thread/qoldbasicatomic.h +++ b/src/corelib/thread/qoldbasicatomic.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,12 +34,13 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef QBASICATOMIC_H -#define QBASICATOMIC_H +#ifndef QOLDBASICATOMIC_H +#define QOLDBASICATOMIC_H #include <QtCore/qglobal.h> @@ -48,7 +48,11 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -QT_MODULE(Core) + +#if 0 +#pragma qt_no_master_include +#pragma qt_sync_stop_processing +#endif class Q_CORE_EXPORT QBasicAtomicInt { @@ -166,10 +170,6 @@ public: QT_END_NAMESPACE QT_END_HEADER -#if defined(QT_MOC) || defined(QT_BUILD_QMAKE) || defined(QT_RCC) || defined(QT_UIC) || defined(QT_BOOTSTRAPPED) -# include <QtCore/qatomic_bootstrap.h> -#else # include <QtCore/qatomic_arch.h> -#endif #endif // QBASIC_ATOMIC diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index 14a29c7edf..4f8378f496 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp index 54926111d5..519bae9fa6 100644 --- a/src/corelib/thread/qreadwritelock.cpp +++ b/src/corelib/thread/qreadwritelock.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h index cdbd7894a1..092352f611 100644 --- a/src/corelib/thread/qreadwritelock.h +++ b/src/corelib/thread/qreadwritelock.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -49,7 +49,6 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -QT_MODULE(Core) #ifndef QT_NO_THREAD diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h index 125245bb4a..85e767ac12 100644 --- a/src/corelib/thread/qreadwritelock_p.h +++ b/src/corelib/thread/qreadwritelock_p.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qrunnable.cpp b/src/corelib/thread/qrunnable.cpp new file mode 100644 index 0000000000..933a5b922c --- /dev/null +++ b/src/corelib/thread/qrunnable.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QRunnable + \since 4.4 + \brief The QRunnable class is the base class for all runnable objects. + + \ingroup thread + + The QRunnable class is an interface for representing a task or + piece of code that needs to be executed, represented by your + reimplementation of the run() function. + + You can use QThreadPool to execute your code in a separate + thread. QThreadPool deletes the QRunnable automatically if + autoDelete() returns true (the default). Use setAutoDelete() to + change the auto-deletion flag. + + QThreadPool supports executing the same QRunnable more than once + by calling QThreadPool::tryStart(this) from within the run() function. + If autoDelete is enabled the QRunnable will be deleted when + the last thread exits the run function. Calling QThreadPool::start() + multiple times with the same QRunnable when autoDelete is enabled + creates a race condition and is not recommended. + + \sa QThreadPool +*/ + +/*! \fn QRunnable::run() + Implement this pure virtual function in your subclass. +*/ + +/*! \fn QRunnable::QRunnable() + Constructs a QRunnable. Auto-deletion is enabled by default. + + \sa autoDelete(), setAutoDelete() +*/ + +/*! \fn QRunnable::~QRunnable() + QRunnable virtual destructor. +*/ + +/*! \fn bool QRunnable::autoDelete() const + + Returns true is auto-deletion is enabled; false otherwise. + + If auto-deletion is enabled, QThreadPool will automatically delete + this runnable after calling run(); otherwise, ownership remains + with the application programmer. + + \sa setAutoDelete(), QThreadPool +*/ + +/*! \fn bool QRunnable::setAutoDelete(bool autoDelete) + + Enables auto-deletion if \a autoDelete is true; otherwise + auto-deletion is disabled. + + If auto-deletion is enabled, QThreadPool will automatically delete + this runnable after calling run(); otherwise, ownership remains + with the application programmer. + + Note that this flag must be set before calling + QThreadPool::start(). Calling this function after + QThreadPool::start() results in undefined behavior. + + \sa autoDelete(), QThreadPool +*/ diff --git a/src/corelib/thread/qrunnable.h b/src/corelib/thread/qrunnable.h new file mode 100644 index 0000000000..11d5c0146e --- /dev/null +++ b/src/corelib/thread/qrunnable.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRUNNABLE_H +#define QRUNNABLE_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + + +class QRunnable +{ + int ref; + + friend class QThreadPool; + friend class QThreadPoolPrivate; + friend class QThreadPoolThread; + +public: + virtual void run() = 0; + + QRunnable() : ref(0) { } + virtual ~QRunnable() { } + + bool autoDelete() const { return ref != -1; } + void setAutoDelete(bool _autoDelete) { ref = _autoDelete ? 0 : -1; } +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index 12539a794d..52f5a1d699 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h index 4790a84bb6..c1d27bbde4 100644 --- a/src/corelib/thread/qsemaphore.h +++ b/src/corelib/thread/qsemaphore.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -48,7 +48,6 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -QT_MODULE(Core) #ifndef QT_NO_THREAD diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 9d48c4dbe5..be0a98d3b5 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -52,24 +52,6 @@ #include "qthread_p.h" #include "private/qcoreapplication_p.h" -/* -#ifdef Q_OS_WIN32 -# include "qt_windows.h" -#else -# include <unistd.h> -# include <netinet/in.h> -# include <sys/utsname.h> -# include <sys/socket.h> -*/ -/* -# elif defined(Q_OS_HPUX) -# include <sys/pstat.h> -# elif defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_MAC) -# include <sys/sysctl.h> -# endif -#endif -*/ - QT_BEGIN_NAMESPACE /* diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index 597e29546a..719f4afbbb 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -50,7 +50,6 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -QT_MODULE(Core) class QThreadData; class QThreadPrivate; diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 094c9b0daf..d8374e9805 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -167,16 +167,13 @@ public: #endif // Q_OS_UNIX -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - HANDLE handle; - unsigned int id; - int waiters; - +#ifdef Q_OS_WIN static unsigned int __stdcall start(void *); static void finish(void *, bool lockAnyway=true); -#endif // Q_OS_WIN32 -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) + Qt::HANDLE handle; + unsigned int id; + int waiters; bool terminationEnabled, terminatePending; # endif QThreadData *data; diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 672b7cb976..9ce951cf3b 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 3184b18471..bdee6d6b7c 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp new file mode 100644 index 0000000000..af8c99197e --- /dev/null +++ b/src/corelib/thread/qthreadpool.cpp @@ -0,0 +1,651 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qthreadpool.h" +#include "qthreadpool_p.h" +#include "qelapsedtimer.h" + +#ifndef QT_NO_THREAD + +QT_BEGIN_NAMESPACE + +inline bool operator<(int priority, const QPair<QRunnable *, int> &p) +{ + return p.second < priority; +} +inline bool operator<(const QPair<QRunnable *, int> &p, int priority) +{ + return priority < p.second; +} + +Q_GLOBAL_STATIC(QThreadPool, theInstance) + +/* + QThread wrapper, provides synchronizitaion against a ThreadPool +*/ +class QThreadPoolThread : public QThread +{ +public: + QThreadPoolThread(QThreadPoolPrivate *manager); + void run(); + void registerTheadInactive(); + + QThreadPoolPrivate *manager; + QRunnable *runnable; +}; + +/* + QThreadPool private class. +*/ + + +/*!\internal + +*/ +QThreadPoolThread::QThreadPoolThread(QThreadPoolPrivate *manager) + :manager(manager), runnable(0) +{ } + +/* \internal + +*/ +void QThreadPoolThread::run() +{ + QMutexLocker locker(&manager->mutex); + for(;;) { + QRunnable *r = runnable; + runnable = 0; + + do { + if (r) { + const bool autoDelete = r->autoDelete(); + + + // run the task + locker.unlock(); +#ifndef QT_NO_EXCEPTIONS + try { +#endif + r->run(); +#ifndef QT_NO_EXCEPTIONS + } catch (...) { + qWarning("Qt Concurrent has caught an exception thrown from a worker thread.\n" + "This is not supported, exceptions thrown in worker threads must be\n" + "caught before control returns to Qt Concurrent."); + registerTheadInactive(); + throw; + } +#endif + locker.relock(); + + if (autoDelete && !--r->ref) + delete r; + } + + // if too many threads are active, expire this thread + if (manager->tooManyThreadsActive()) + break; + + r = !manager->queue.isEmpty() ? manager->queue.takeFirst().first : 0; + } while (r != 0); + + if (manager->isExiting) { + registerTheadInactive(); + break; + } + + // if too many threads are active, expire this thread + bool expired = manager->tooManyThreadsActive(); + if (!expired) { + ++manager->waitingThreads; + registerTheadInactive(); + // wait for work, exiting after the expiry timeout is reached + expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout); + ++manager->activeThreads; + + if (expired) + --manager->waitingThreads; + } + if (expired) { + manager->expiredThreads.enqueue(this); + registerTheadInactive(); + break; + } + } +} + +void QThreadPoolThread::registerTheadInactive() +{ + if (--manager->activeThreads == 0) + manager->noActiveThreads.wakeAll(); +} + + +/* \internal + +*/ +QThreadPoolPrivate:: QThreadPoolPrivate() + : isExiting(false), + expiryTimeout(30000), + maxThreadCount(qAbs(QThread::idealThreadCount())), + reservedThreads(0), + waitingThreads(0), + activeThreads(0) +{ } + +bool QThreadPoolPrivate::tryStart(QRunnable *task) +{ + if (allThreads.isEmpty()) { + // always create at least one thread + startThread(task); + return true; + } + + // can't do anything if we're over the limit + if (activeThreadCount() >= maxThreadCount) + return false; + + if (waitingThreads > 0) { + // recycle an available thread + --waitingThreads; + enqueueTask(task); + return true; + } + + if (!expiredThreads.isEmpty()) { + // restart an expired thread + QThreadPoolThread *thread = expiredThreads.dequeue(); + Q_ASSERT(thread->runnable == 0); + + ++activeThreads; + + if (task->autoDelete()) + ++task->ref; + thread->runnable = task; + thread->start(); + return true; + } + + // start a new thread + startThread(task); + return true; +} + +void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority) +{ + if (runnable->autoDelete()) + ++runnable->ref; + + // put it on the queue + QList<QPair<QRunnable *, int> >::iterator at = + qUpperBound(queue.begin(), queue.end(), priority); + queue.insert(at, qMakePair(runnable, priority)); + runnableReady.wakeOne(); +} + +int QThreadPoolPrivate::activeThreadCount() const +{ + // To improve scalability this function is called without holding + // the mutex lock -- keep it thread-safe. + return (allThreads.count() + - expiredThreads.count() + - waitingThreads + + reservedThreads); +} + +void QThreadPoolPrivate::tryToStartMoreThreads() +{ + // try to push tasks on the queue to any available threads + while (!queue.isEmpty() && tryStart(queue.first().first)) + queue.removeFirst(); +} + +bool QThreadPoolPrivate::tooManyThreadsActive() const +{ + const int activeThreadCount = this->activeThreadCount(); + return activeThreadCount > maxThreadCount && (activeThreadCount - reservedThreads) > 1; +} + +/*! \internal + +*/ +void QThreadPoolPrivate::startThread(QRunnable *runnable) +{ + QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this)); + thread->setObjectName(QLatin1String("Thread (pooled)")); + allThreads.insert(thread.data()); + ++activeThreads; + + if (runnable->autoDelete()) + ++runnable->ref; + thread->runnable = runnable; + thread.take()->start(); +} + +/*! \internal + Makes all threads exit, waits for each tread to exit and deletes it. +*/ +void QThreadPoolPrivate::reset() +{ + QMutexLocker locker(&mutex); + isExiting = true; + runnableReady.wakeAll(); + + do { + // make a copy of the set so that we can iterate without the lock + QSet<QThreadPoolThread *> allThreadsCopy = allThreads; + allThreads.clear(); + locker.unlock(); + + foreach (QThreadPoolThread *thread, allThreadsCopy) { + thread->wait(); + delete thread; + } + + locker.relock(); + // repeat until all newly arrived threads have also completed + } while (!allThreads.isEmpty()); + + waitingThreads = 0; + expiredThreads.clear(); + + isExiting = false; +} + +bool QThreadPoolPrivate::waitForDone(int msecs) +{ + QMutexLocker locker(&mutex); + if (msecs < 0) { + while (!(queue.isEmpty() && activeThreads == 0)) + noActiveThreads.wait(locker.mutex()); + } else { + QElapsedTimer timer; + timer.start(); + int t; + while (!(queue.isEmpty() && activeThreads == 0) && + ((t = msecs - timer.elapsed()) > 0)) + noActiveThreads.wait(locker.mutex(), t); + } + return queue.isEmpty() && activeThreads == 0; +} + +/*! \internal + Pulls a runnable from the front queue and runs it in the current thread. Blocks + until the runnable has completed. Returns true if a runnable was found. +*/ +bool QThreadPoolPrivate::startFrontRunnable() +{ + QMutexLocker locker(&mutex); + if (queue.isEmpty()) + return false; + + QRunnable *runnable = queue.takeFirst().first; + const bool autoDelete = runnable->autoDelete(); + bool del = autoDelete && !--runnable->ref; + + locker.unlock(); + runnable->run(); + locker.relock(); + + if (del) { + delete runnable; + } + + return true; +} + +/*! \internal + Seaches for \a runnable in the queue, removes it from the queue and + runs it if found. This functon does not return until the runnable + has completed. +*/ +void QThreadPoolPrivate::stealRunnable(QRunnable *runnable) +{ + if (runnable == 0 || queue.isEmpty()) + return; + bool found = false; + { + QMutexLocker locker(&mutex); + QList<QPair<QRunnable *, int> >::iterator it = queue.begin(); + QList<QPair<QRunnable *, int> >::iterator end = queue.end(); + + while (it != end) { + if (it->first == runnable) { + found = true; + queue.erase(it); + break; + } + ++it; + } + } + + if (!found) + return; + + const bool autoDelete = runnable->autoDelete(); + bool del = autoDelete && !--runnable->ref; + + runnable->run(); + + if (del) { + delete runnable; + } +} + +/*! + \class QThreadPool + \brief The QThreadPool class manages a collection of QThreads. + \since 4.4 + \threadsafe + + \ingroup thread + + QThreadPool manages and recyles individual QThread objects to help reduce + thread creation costs in programs that use threads. Each Qt application + has one global QThreadPool object, which can be accessed by calling + globalInstance(). + + To use one of the QThreadPool threads, subclass QRunnable and implement + the run() virtual function. Then create an object of that class and pass + it to QThreadPool::start(). + + \snippet doc/src/snippets/code/src_corelib_concurrent_qthreadpool.cpp 0 + + QThreadPool deletes the QRunnable automatically by default. Use + QRunnable::setAutoDelete() to change the auto-deletion flag. + + QThreadPool supports executing the same QRunnable more than once + by calling tryStart(this) from within QRunnable::run(). + If autoDelete is enabled the QRunnable will be deleted when + the last thread exits the run function. Calling start() + multiple times with the same QRunnable when autoDelete is enabled + creates a race condition and is not recommended. + + Threads that are unused for a certain amount of time will expire. The + default expiry timeout is 30000 milliseconds (30 seconds). This can be + changed using setExpiryTimeout(). Setting a negative expiry timeout + disables the expiry mechanism. + + Call maxThreadCount() to query the maximum number of threads to be used. + If needed, you can change the limit with setMaxThreadCount(). The default + maxThreadCount() is QThread::idealThreadCount(). The activeThreadCount() + function returns the number of threads currently doing work. + + The reserveThread() function reserves a thread for external + use. Use releaseThread() when your are done with the thread, so + that it may be reused. Essentially, these functions temporarily + increase or reduce the active thread count and are useful when + implementing time-consuming operations that are not visible to the + QThreadPool. + + Note that QThreadPool is a low-level class for managing threads, see + QtConcurrent::run() or the other + \l {Concurrent Programming}{Qt Concurrent} APIs for higher + level alternatives. + + \sa QRunnable +*/ + +/*! + Constructs a thread pool with the given \a parent. +*/ +QThreadPool::QThreadPool(QObject *parent) + : QObject(*new QThreadPoolPrivate, parent) +{ } + +/*! + Destroys the QThreadPool. + This function will block until all runnables have been completed. +*/ +QThreadPool::~QThreadPool() +{ + d_func()->waitForDone(); + d_func()->reset(); +} + +/*! + Returns the global QThreadPool instance. +*/ +QThreadPool *QThreadPool::globalInstance() +{ + return theInstance(); +} + +/*! + Reserves a thread and uses it to run \a runnable, unless this thread will + make the current thread count exceed maxThreadCount(). In that case, + \a runnable is added to a run queue instead. The \a priority argument can + be used to control the run queue's order of execution. + + Note that the thread pool takes ownership of the \a runnable if + \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns true, + and the \a runnable will be deleted automatically by the thread + pool after the \l{QRunnable::run()}{runnable->run()} returns. If + \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns false, + ownership of \a runnable remains with the caller. Note that + changing the auto-deletion on \a runnable after calling this + functions results in undefined behavior. +*/ +void QThreadPool::start(QRunnable *runnable, int priority) +{ + if (!runnable) + return; + + Q_D(QThreadPool); + QMutexLocker locker(&d->mutex); + if (!d->tryStart(runnable)) + d->enqueueTask(runnable, priority); +} + +/*! + Attempts to reserve a thread to run \a runnable. + + If no threads are available at the time of calling, then this function + does nothing and returns false. Otherwise, \a runnable is run immediately + using one available thread and this function returns true. + + Note that the thread pool takes ownership of the \a runnable if + \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns true, + and the \a runnable will be deleted automatically by the thread + pool after the \l{QRunnable::run()}{runnable->run()} returns. If + \l{QRunnable::autoDelete()}{runnable->autoDelete()} returns false, + ownership of \a runnable remains with the caller. Note that + changing the auto-deletion on \a runnable after calling this + function results in undefined behavior. +*/ +bool QThreadPool::tryStart(QRunnable *runnable) +{ + if (!runnable) + return false; + + Q_D(QThreadPool); + + // To improve scalability perform a check on the thread count + // before locking the mutex. + if (d->allThreads.isEmpty() == false && d->activeThreadCount() >= d->maxThreadCount) + return false; + + QMutexLocker locker(&d->mutex); + return d->tryStart(runnable); +} + +/*! \property QThreadPool::expiryTimeout + + Threads that are unused for \a expiryTimeout milliseconds are considered + to have expired and will exit. Such threads will be restarted as needed. + The default \a expiryTimeout is 30000 milliseconds (30 seconds). If + \a expiryTimeout is negative, newly created threads will not expire, e.g., + they will not exit until the thread pool is destroyed. + + Note that setting \a expiryTimeout has no effect on already running + threads. Only newly created threads will use the new \a expiryTimeout. + We recommend setting the \a expiryTimeout immediately after creating the + thread pool, but before calling start(). +*/ + +int QThreadPool::expiryTimeout() const +{ + Q_D(const QThreadPool); + return d->expiryTimeout; +} + +void QThreadPool::setExpiryTimeout(int expiryTimeout) +{ + Q_D(QThreadPool); + if (d->expiryTimeout == expiryTimeout) + return; + d->expiryTimeout = expiryTimeout; +} + +/*! \property QThreadPool::maxThreadCount + + This property represents the maximum number of threads used by the thread + pool. + + \note The thread pool will always use at least 1 thread, even if + \a maxThreadCount limit is zero or negative. + + The default \a maxThreadCount is QThread::idealThreadCount(). +*/ + +int QThreadPool::maxThreadCount() const +{ + Q_D(const QThreadPool); + return d->maxThreadCount; +} + +void QThreadPool::setMaxThreadCount(int maxThreadCount) +{ + Q_D(QThreadPool); + QMutexLocker locker(&d->mutex); + + if (maxThreadCount == d->maxThreadCount) + return; + + d->maxThreadCount = maxThreadCount; + d->tryToStartMoreThreads(); +} + +/*! \property QThreadPool::activeThreadCount + + This property represents the number of active threads in the thread pool. + + \note It is possible for this function to return a value that is greater + than maxThreadCount(). See reserveThread() for more details. + + \sa reserveThread(), releaseThread() +*/ + +int QThreadPool::activeThreadCount() const +{ + Q_D(const QThreadPool); + return d->activeThreadCount(); +} + +/*! + Reserves one thread, disregarding activeThreadCount() and maxThreadCount(). + + Once you are done with the thread, call releaseThread() to allow it to be + reused. + + \note This function will always increase the number of active threads. + This means that by using this function, it is possible for + activeThreadCount() to return a value greater than maxThreadCount() . + + \sa releaseThread() + */ +void QThreadPool::reserveThread() +{ + Q_D(QThreadPool); + QMutexLocker locker(&d->mutex); + ++d->reservedThreads; +} + +/*! + Releases a thread previously reserved by a call to reserveThread(). + + \note Calling this function without previously reserving a thread + temporarily increases maxThreadCount(). This is useful when a + thread goes to sleep waiting for more work, allowing other threads + to continue. Be sure to call reserveThread() when done waiting, so + that the thread pool can correctly maintain the + activeThreadCount(). + + \sa reserveThread() +*/ +void QThreadPool::releaseThread() +{ + Q_D(QThreadPool); + QMutexLocker locker(&d->mutex); + --d->reservedThreads; + d->tryToStartMoreThreads(); +} + +/*! + Waits for each thread to exit and removes all threads from the thread pool. +*/ +void QThreadPool::waitForDone() +{ + Q_D(QThreadPool); + d->waitForDone(); + d->reset(); +} + +/*! + \overload waitForDone() + \since 4.8 + + Waits up to \a msecs milliseconds for all threads to exit and removes all + threads from the thread pool. Returns true if all threads were removed; + otherwise it returns false. +*/ +bool QThreadPool::waitForDone(int msecs) +{ + Q_D(QThreadPool); + bool rc = d->waitForDone(msecs); + if (rc) + d->reset(); + return rc; +} + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h new file mode 100644 index 0000000000..9fc023c56d --- /dev/null +++ b/src/corelib/thread/qthreadpool.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTHREADPOOL_H +#define QTHREADPOOL_H + +#include <QtCore/qglobal.h> + +#include <QtCore/qthread.h> +#include <QtCore/qrunnable.h> + +#ifndef QT_NO_THREAD + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + + +class QThreadPoolPrivate; +class Q_CORE_EXPORT QThreadPool : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QThreadPool) + Q_PROPERTY(int expiryTimeout READ expiryTimeout WRITE setExpiryTimeout) + Q_PROPERTY(int maxThreadCount READ maxThreadCount WRITE setMaxThreadCount) + Q_PROPERTY(int activeThreadCount READ activeThreadCount) + friend class QFutureInterfaceBase; + +public: + QThreadPool(QObject *parent = 0); + ~QThreadPool(); + + static QThreadPool *globalInstance(); + + void start(QRunnable *runnable, int priority = 0); + bool tryStart(QRunnable *runnable); + + int expiryTimeout() const; + void setExpiryTimeout(int expiryTimeout); + + int maxThreadCount() const; + void setMaxThreadCount(int maxThreadCount); + + int activeThreadCount() const; + + void reserveThread(); + void releaseThread(); + + void waitForDone(); + bool waitForDone(int msecs); +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // QT_NO_THREAD + +#endif diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h new file mode 100644 index 0000000000..9a7c09695f --- /dev/null +++ b/src/corelib/thread/qthreadpool_p.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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.1, 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTHREADPOOL_P_H +#define QTHREADPOOL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +// + +#include "QtCore/qmutex.h" +#include "QtCore/qwaitcondition.h" +#include "QtCore/qset.h" +#include "QtCore/qqueue.h" +#include "private/qobject_p.h" + +#ifndef QT_NO_THREAD + +QT_BEGIN_NAMESPACE + +class QThreadPoolThread; +class Q_CORE_EXPORT QThreadPoolPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QThreadPool) + friend class QThreadPoolThread; + +public: + QThreadPoolPrivate(); + + bool tryStart(QRunnable *task); + void enqueueTask(QRunnable *task, int priority = 0); + int activeThreadCount() const; + + void tryToStartMoreThreads(); + bool tooManyThreadsActive() const; + + void startThread(QRunnable *runnable = 0); + void reset(); + bool waitForDone(int msecs = -1); + bool startFrontRunnable(); + void stealRunnable(QRunnable *); + + mutable QMutex mutex; + QWaitCondition runnableReady; + QSet<QThreadPoolThread *> allThreads; + QQueue<QThreadPoolThread *> expiredThreads; + QList<QPair<QRunnable *, int> > queue; + QWaitCondition noActiveThreads; + + bool isExiting; + int expiryTimeout; + int maxThreadCount; + int reservedThreads; + int waitingThreads; + int activeThreads; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_THREAD +#endif diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp index 6dba8d670e..1dfa3305bc 100644 --- a/src/corelib/thread/qthreadstorage.cpp +++ b/src/corelib/thread/qthreadstorage.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -71,13 +71,13 @@ void qtsDebug(const char *fmt, ...) # define DEBUG_MSG if(false)qDebug #endif -Q_GLOBAL_STATIC(QMutex, mutex) +static QBasicMutex destructorsMutex; typedef QVector<void (*)(void *)> DestructorMap; Q_GLOBAL_STATIC(DestructorMap, destructors) QThreadStorageData::QThreadStorageData(void (*func)(void *)) { - QMutexLocker locker(mutex()); + QMutexLocker locker(&destructorsMutex); DestructorMap *destr = destructors(); if (!destr) { /* @@ -109,7 +109,7 @@ QThreadStorageData::QThreadStorageData(void (*func)(void *)) QThreadStorageData::~QThreadStorageData() { DEBUG_MSG("QThreadStorageData: Released id %d", id); - QMutexLocker locker(mutex()); + QMutexLocker locker(&destructorsMutex); if (destructors()) (*destructors())[id] = 0; } @@ -153,7 +153,7 @@ void **QThreadStorageData::set(void *p) value, data->thread); - QMutexLocker locker(mutex()); + QMutexLocker locker(&destructorsMutex); DestructorMap *destr = destructors(); void (*destructor)(void *) = destr ? destr->value(id) : 0; locker.unlock(); @@ -174,7 +174,7 @@ void **QThreadStorageData::set(void *p) void QThreadStorageData::finish(void **p) { QVector<void *> *tls = reinterpret_cast<QVector<void *> *>(p); - if (!tls || tls->isEmpty() || !mutex()) + if (!tls || tls->isEmpty() || !destructors()) return; // nothing to do DEBUG_MSG("QThreadStorageData: Destroying storage for thread %p", QThread::currentThread()); @@ -190,7 +190,7 @@ void QThreadStorageData::finish(void **p) continue; } - QMutexLocker locker(mutex()); + QMutexLocker locker(&destructorsMutex); void (*destructor)(void *) = destructors()->value(i); locker.unlock(); diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h index 790f9a51ef..706d4d0e86 100644 --- a/src/corelib/thread/qthreadstorage.h +++ b/src/corelib/thread/qthreadstorage.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -50,7 +50,6 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -QT_MODULE(Core) class Q_CORE_EXPORT QThreadStorageData { diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h index 7d4eb684ee..f6e41aef4e 100644 --- a/src/corelib/thread/qwaitcondition.h +++ b/src/corelib/thread/qwaitcondition.h @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -50,7 +50,6 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -QT_MODULE(Core) #ifndef QT_NO_THREAD diff --git a/src/corelib/thread/qwaitcondition.qdoc b/src/corelib/thread/qwaitcondition.qdoc index f079e5a6ba..7b861f8f7a 100644 --- a/src/corelib/thread/qwaitcondition.qdoc +++ b/src/corelib/thread/qwaitcondition.qdoc @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the documentation of the Qt Toolkit. ** @@ -21,6 +20,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp index 91aea010d9..5641eba80a 100644 --- a/src/corelib/thread/qwaitcondition_unix.cpp +++ b/src/corelib/thread/qwaitcondition_unix.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index 0106dbf13a..3528d6a0ff 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -1,8 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: http://www.qt-project.org/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -35,6 +34,7 @@ ** ** ** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -45,13 +45,13 @@ #include "qreadwritelock.h" #include "qlist.h" #include "qalgorithms.h" -#include "qt_windows.h" #ifndef QT_NO_THREAD #define Q_MUTEX_T void* #include <private/qmutex_p.h> #include <private/qreadwritelock_p.h> +#include <qt_windows.h> QT_BEGIN_NAMESPACE diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 974e086684..1eefa60d50 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -2,12 +2,16 @@ # public headers HEADERS += thread/qmutex.h \ + thread/qrunnable.h \ thread/qreadwritelock.h \ thread/qsemaphore.h \ thread/qthread.h \ + thread/qthreadpool.h \ thread/qthreadstorage.h \ thread/qwaitcondition.h \ thread/qatomic.h \ + thread/qbasicatomic.h \ + thread/qgenericatomic.h \ thread/qoldbasicatomic.h # private headers @@ -15,14 +19,17 @@ HEADERS += thread/qmutex_p.h \ thread/qmutexpool_p.h \ thread/qorderedmutexlocker_p.h \ thread/qreadwritelock_p.h \ - thread/qthread_p.h + thread/qthread_p.h \ + thread/qthreadpool_p.h SOURCES += thread/qatomic.cpp \ thread/qmutex.cpp \ thread/qreadwritelock.cpp \ + thread/qrunnable.cpp \ thread/qmutexpool.cpp \ thread/qsemaphore.cpp \ thread/qthread.cpp \ + thread/qthreadpool.cpp \ thread/qthreadstorage.cpp unix:SOURCES += thread/qthread_unix.cpp \ |