diff options
Diffstat (limited to 'src/corelib/thread')
-rw-r--r-- | src/corelib/thread/qatomic.cpp | 7 | ||||
-rw-r--r-- | src/corelib/thread/qatomic.h | 2 | ||||
-rw-r--r-- | src/corelib/thread/qbasicatomic.h | 23 | ||||
-rw-r--r-- | src/corelib/thread/qmutex_win.cpp | 9 | ||||
-rw-r--r-- | src/corelib/thread/qoldbasicatomic.h | 143 | ||||
-rw-r--r-- | src/corelib/thread/qthread.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qthread_p.h | 9 | ||||
-rw-r--r-- | src/corelib/thread/qthread_win.cpp | 154 | ||||
-rw-r--r-- | src/corelib/thread/qthreadpool.cpp | 28 | ||||
-rw-r--r-- | src/corelib/thread/qthreadpool_p.h | 3 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition.h | 6 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition_win.cpp | 11 | ||||
-rw-r--r-- | src/corelib/thread/thread.pri | 3 |
13 files changed, 209 insertions, 191 deletions
diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp index 39d136c006..b2e19dc6dc 100644 --- a/src/corelib/thread/qatomic.cpp +++ b/src/corelib/thread/qatomic.cpp @@ -39,6 +39,8 @@ ** ****************************************************************************/ +#include "qatomic.h" + /*! \class QAtomicInt \inmodule QtCore @@ -1126,3 +1128,8 @@ Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE to indicate that the atomic fetch-and-add on pointers is wait-free. */ + +// static checks +#ifndef Q_ATOMIC_INT32_IS_SUPPORTED +# error "Q_ATOMIC_INT32_IS_SUPPORTED must be defined" +#endif diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h index 1ccaecc135..78eff2a710 100644 --- a/src/corelib/thread/qatomic.h +++ b/src/corelib/thread/qatomic.h @@ -59,7 +59,7 @@ class QAtomicInt : public QBasicAtomicInt { public: // Non-atomic API -#ifdef Q_BASIC_ATOMIC_HAS_CONSTRUCTORS +#ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS constexpr QAtomicInt(int value = 0) Q_DECL_NOTHROW : QBasicAtomicInt(value) {} #else inline QAtomicInt(int value = 0) Q_DECL_NOTHROW diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index 782ae90698..9fa12ba811 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -51,33 +51,17 @@ #elif defined(Q_CC_MSVC) # include <QtCore/qatomic_msvc.h> -// Operating system dependent implementation -#elif defined(Q_OS_INTEGRITY) -# include "QtCore/qatomic_integrity.h" -#elif defined(Q_OS_VXWORKS) -# include "QtCore/qatomic_vxworks.h" - // Processor dependent implementation -#elif defined(Q_PROCESSOR_ALPHA) -# include "QtCore/qatomic_alpha.h" #elif defined(Q_PROCESSOR_ARM_V7) && defined(Q_PROCESSOR_ARM_32) # include "QtCore/qatomic_armv7.h" #elif defined(Q_PROCESSOR_ARM_V6) && defined(Q_PROCESSOR_ARM_32) # include "QtCore/qatomic_armv6.h" #elif defined(Q_PROCESSOR_ARM_V5) && defined(Q_PROCESSOR_ARM_32) # include "QtCore/qatomic_armv5.h" -#elif defined(Q_PROCESSOR_BFIN) -# include "QtCore/qatomic_bfin.h" #elif defined(Q_PROCESSOR_IA64) # include "QtCore/qatomic_ia64.h" #elif defined(Q_PROCESSOR_MIPS) # include "QtCore/qatomic_mips.h" -#elif defined(Q_PROCESSOR_POWER) -# include "QtCore/qatomic_power.h" -#elif defined(Q_PROCESSOR_S390) -# include "QtCore/qatomic_s390.h" -#elif defined(Q_PROCESSOR_SH4A) -# include "QtCore/qatomic_sh4a.h" #elif defined(Q_PROCESSOR_SPARC) # include "QtCore/qatomic_sparc.h" #elif defined(Q_PROCESSOR_X86) @@ -98,9 +82,6 @@ # error "Qt has not been ported to this platform" #endif -// Only include if the implementation has been ported to QAtomicOps -#ifndef QOLDBASICATOMIC_H - QT_BEGIN_NAMESPACE #if 0 @@ -133,7 +114,7 @@ class QBasicAtomicInteger public: typedef QAtomicOps<T> Ops; // static check that this is a valid integer - typedef char PermittedIntegerType[QAtomicIntegerTraits<T>::IsInteger ? 1 : -1]; + Q_STATIC_ASSERT_X(QAtomicIntegerTraits<T>::IsInteger, "Template parameter is not a supported integer on this platform"); typename Ops::Type _q_value; @@ -266,6 +247,4 @@ public: QT_END_NAMESPACE -#endif // QOLDBASICATOMIC_H - #endif // QBASICATOMIC_H diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index 14b7f34008..a8cdf85fb6 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -48,7 +48,12 @@ QT_BEGIN_NAMESPACE QMutexPrivate::QMutexPrivate() { +#ifndef Q_OS_WINRT event = CreateEvent(0, FALSE, FALSE, 0); +#else + event = CreateEventEx(0, NULL, 0, EVENT_ALL_ACCESS); +#endif + if (!event) qWarning("QMutexData::QMutexData: Cannot create event"); } @@ -58,7 +63,11 @@ QMutexPrivate::~QMutexPrivate() bool QMutexPrivate::wait(int timeout) { +#ifndef Q_OS_WINRT return (WaitForSingleObject(event, timeout < 0 ? INFINITE : timeout) == WAIT_OBJECT_0); +#else + return (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0); +#endif } void QMutexPrivate::wakeUp() Q_DECL_NOTHROW diff --git a/src/corelib/thread/qoldbasicatomic.h b/src/corelib/thread/qoldbasicatomic.h deleted file mode 100644 index b755256ff7..0000000000 --- a/src/corelib/thread/qoldbasicatomic.h +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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, Digia gives you certain additional -** rights. These rights are described in the Digia 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. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOLDBASICATOMIC_H -#define QOLDBASICATOMIC_H - -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -#pragma qt_sync_skip_header_check -#pragma qt_no_master_include -#pragma qt_sync_stop_processing -#endif - -class Q_CORE_EXPORT QBasicAtomicInt -{ -public: - volatile int _q_value; - - // Atomic API, implemented in qatomic_XXX.h - - int load() const { return _q_value; } - int loadAcquire() { return _q_value; } - void store(int newValue) { _q_value = newValue; } - void storeRelease(int newValue) { _q_value = newValue; } - - static bool isReferenceCountingNative(); - static bool isReferenceCountingWaitFree(); - - bool ref(); - bool deref(); - - static bool isTestAndSetNative(); - static bool isTestAndSetWaitFree(); - - bool testAndSetRelaxed(int expectedValue, int newValue); - bool testAndSetAcquire(int expectedValue, int newValue); - bool testAndSetRelease(int expectedValue, int newValue); - bool testAndSetOrdered(int expectedValue, int newValue); - - static bool isFetchAndStoreNative(); - static bool isFetchAndStoreWaitFree(); - - int fetchAndStoreRelaxed(int newValue); - int fetchAndStoreAcquire(int newValue); - int fetchAndStoreRelease(int newValue); - int fetchAndStoreOrdered(int newValue); - - static bool isFetchAndAddNative(); - static bool isFetchAndAddWaitFree(); - - int fetchAndAddRelaxed(int valueToAdd); - int fetchAndAddAcquire(int valueToAdd); - int fetchAndAddRelease(int valueToAdd); - int fetchAndAddOrdered(int valueToAdd); -}; - -template <typename T> -class QBasicAtomicPointer -{ -public: - T * volatile _q_value; - - // Atomic API, implemented in qatomic_XXX.h - - T *load() const { return _q_value; } - T *loadAcquire() { return _q_value; } - void store(T *newValue) { _q_value = newValue; } - void storeRelease(T *newValue) { _q_value = newValue; } - - static bool isTestAndSetNative(); - static bool isTestAndSetWaitFree(); - - bool testAndSetRelaxed(T *expectedValue, T *newValue); - bool testAndSetAcquire(T *expectedValue, T *newValue); - bool testAndSetRelease(T *expectedValue, T *newValue); - bool testAndSetOrdered(T *expectedValue, T *newValue); - - static bool isFetchAndStoreNative(); - static bool isFetchAndStoreWaitFree(); - - T *fetchAndStoreRelaxed(T *newValue); - T *fetchAndStoreAcquire(T *newValue); - T *fetchAndStoreRelease(T *newValue); - T *fetchAndStoreOrdered(T *newValue); - - static bool isFetchAndAddNative(); - static bool isFetchAndAddWaitFree(); - - T *fetchAndAddRelaxed(qptrdiff valueToAdd); - T *fetchAndAddAcquire(qptrdiff valueToAdd); - T *fetchAndAddRelease(qptrdiff valueToAdd); - T *fetchAndAddOrdered(qptrdiff valueToAdd); -}; - -#define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) } - -QT_END_NAMESPACE - -#endif // QOLDBASICATOMIC_H diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 50ccca9eda..adad4b81a1 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -154,7 +154,9 @@ QThreadPrivate::QThreadPrivate(QThreadData *d) thread_id = 0; #elif defined (Q_OS_WIN) handle = 0; +# ifndef Q_OS_WINRT id = 0; +# endif waiters = 0; #endif #if defined (Q_OS_WIN) diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index fce84e881b..e2951b125f 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -66,6 +66,10 @@ #include <algorithm> +#ifdef Q_OS_WINRT +#include <thread> +#endif + QT_BEGIN_NAMESPACE class QAbstractEventDispatcher; @@ -173,8 +177,13 @@ public: static unsigned int __stdcall start(void *); static void finish(void *, bool lockAnyway=true); +# ifndef Q_OS_WINRT Qt::HANDLE handle; unsigned int id; +# else + std::thread *handle; + std::thread::id id; +# endif int waiters; bool terminationEnabled, terminatePending; # endif diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 865b1e6af5..03c5b943d6 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ //#define WINVER 0x0500 -#if _WIN32_WINNT < 0x0400 +#if (_WIN32_WINNT < 0x0400) && !defined(Q_OS_WINRT) #define _WIN32_WINNT 0x0400 #endif @@ -54,10 +54,17 @@ #include <qpointer.h> #include <private/qcoreapplication_p.h> +#ifdef Q_OS_WINRT +#include <private/qeventdispatcher_winrt_p.h> +#else #include <private/qeventdispatcher_win_p.h> +#endif #include <qt_windows.h> +#ifdef Q_OS_WINRT +#include <thread> +#endif #ifndef Q_OS_WINCE #ifndef _MT @@ -71,6 +78,7 @@ #ifndef QT_NO_THREAD QT_BEGIN_NAMESPACE +#ifndef Q_OS_WINRT void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread); DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID); @@ -92,6 +100,38 @@ static void qt_free_tls() } } Q_DESTRUCTOR_FUNCTION(qt_free_tls) +#else // !Q_OS_WINRT + +__declspec(thread) static QThreadData* qt_current_thread_data_tls_index = 0; +void qt_create_tls() +{ +} + +static void qt_free_tls() +{ + if (qt_current_thread_data_tls_index) { + qt_current_thread_data_tls_index->deref(); + qt_current_thread_data_tls_index = 0; + } +} + +QThreadData* TlsGetValue(QThreadData*& tls) +{ + Q_ASSERT(tls == qt_current_thread_data_tls_index); + return tls; +} + +void TlsSetValue(QThreadData*& tls, QThreadData* data) +{ + Q_ASSERT(tls == qt_current_thread_data_tls_index); + if (tls) + tls->deref(); + tls = data; + if (tls) + tls->ref(); +} +Q_DESTRUCTOR_FUNCTION(qt_free_tls) +#endif // Q_OS_WINRT /* QThreadData @@ -124,6 +164,9 @@ QThreadData *QThreadData::current(bool createIfNecessary) if (!QCoreApplicationPrivate::theMainThread) { QCoreApplicationPrivate::theMainThread = threadData->thread; +#ifndef Q_OS_WINRT + // TODO: is there a way to reflect the branch's behavior using + // WinRT API? } else { HANDLE realHandle = INVALID_HANDLE_VALUE; #if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600)) @@ -138,6 +181,7 @@ QThreadData *QThreadData::current(bool createIfNecessary) realHandle = reinterpret_cast<HANDLE>(GetCurrentThreadId()); #endif qt_watch_adopted_thread(realHandle, threadData->thread); +#endif // !Q_OS_WINRT } } return threadData; @@ -145,10 +189,16 @@ QThreadData *QThreadData::current(bool createIfNecessary) void QAdoptedThread::init() { +#ifndef Q_OS_WINRT d_func()->handle = GetCurrentThread(); d_func()->id = GetCurrentThreadId(); +#else + d_func()->handle = nullptr; + d_func()->id = std::this_thread::get_id(); +#endif } +#ifndef Q_OS_WINRT static QVector<HANDLE> qt_adopted_thread_handles; static QVector<QThread *> qt_adopted_qthreads; static QMutex qt_adopted_thread_watcher_mutex; @@ -301,6 +351,7 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) } } #endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE +#endif // !Q_OS_WINRT /************************************************************************** ** QThreadPrivate @@ -310,7 +361,11 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) void QThreadPrivate::createEventDispatcher(QThreadData *data) { +#ifdef Q_OS_WINRT + QEventDispatcherWinRT *theEventDispatcher = new QEventDispatcherWinRT; +#else QEventDispatcherWin32 *theEventDispatcher = new QEventDispatcherWin32; +#endif data->eventDispatcher.storeRelease(theEventDispatcher); theEventDispatcher->startingUp(); } @@ -338,7 +393,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi else createEventDispatcher(data); -#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) +#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) // sets the name of the current thread. QByteArray objectName = thr->objectName().toLocal8Bit(); qt_set_thread_name((HANDLE)-1, @@ -384,11 +439,20 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) d->interruptionRequested = false; if (!d->waiters) { +#ifndef Q_OS_WINRT CloseHandle(d->handle); +#else + CloseHandle(d->handle->native_handle()); + delete d->handle; +#endif d->handle = 0; } +#ifndef Q_OS_WINRT d->id = 0; +#else + d->id = std::thread::id(); +#endif } @@ -404,10 +468,15 @@ Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW int QThread::idealThreadCount() Q_DECL_NOTHROW { SYSTEM_INFO sysinfo; +#ifndef Q_OS_WINRT GetSystemInfo(&sysinfo); +#else + GetNativeSystemInfo(&sysinfo); +#endif return sysinfo.dwNumberOfProcessors; } +#ifndef Q_OS_WINRT void QThread::yieldCurrentThread() { #ifndef Q_OS_WINCE @@ -431,7 +500,28 @@ void QThread::usleep(unsigned long usecs) { ::Sleep((usecs / 1000) + 1); } +#else // !Q_OS_WINRT + +void QThread::yieldCurrentThread() +{ + std::this_thread::yield(); +} +void QThread::sleep(unsigned long secs) +{ + std::this_thread::sleep_for(std::chrono::seconds(secs)); +} + +void QThread::msleep(unsigned long msecs) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(msecs)); +} + +void QThread::usleep(unsigned long usecs) +{ + std::this_thread::sleep_for(std::chrono::microseconds(usecs)); +} +#endif // Q_OS_WINRT void QThread::start(Priority priority) { @@ -453,6 +543,7 @@ void QThread::start(Priority priority) d->returnCode = 0; d->interruptionRequested = false; +#ifndef Q_OS_WINRT /* NOTE: we create the thread in the suspended state, set the priority and then resume the thread. @@ -517,6 +608,23 @@ void QThread::start(Priority priority) if (ResumeThread(d->handle) == (DWORD) -1) { qErrnoWarning("QThread::start: Failed to resume new thread"); } +#else // !Q_OS_WINRT + d->handle = new std::thread(QThreadPrivate::start, this); + + if (!d->handle) { + qErrnoWarning(errno, "QThread::start: Failed to create thread"); + d->running = false; + d->finished = true; + return; + } + + d->id = d->handle->get_id(); + + if (priority != NormalPriority || priority != InheritPriority) { + qWarning("QThread::start: Failed to set thread priority (not implemented)"); + d->priority = NormalPriority; + } +#endif // Q_OS_WINRT } void QThread::terminate() @@ -529,7 +637,14 @@ void QThread::terminate() d->terminatePending = true; return; } + +#ifndef Q_OS_WINRT TerminateThread(d->handle, 0); +#else // !Q_OS_WINRT + qWarning("QThread::terminate: Terminate is not supported on WinRT"); + CloseHandle(d->handle->native_handle()); + d->handle = 0; +#endif // Q_OS_WINRT QThreadPrivate::finish(this, false); } @@ -538,7 +653,11 @@ bool QThread::wait(unsigned long time) Q_D(QThread); QMutexLocker locker(&d->mutex); +#ifndef Q_OS_WINRT if (d->id == GetCurrentThreadId()) { +#else + if (d->id == std::this_thread::get_id()) { +#endif qWarning("QThread::wait: Thread tried to wait on itself"); return false; } @@ -549,6 +668,7 @@ bool QThread::wait(unsigned long time) locker.mutex()->unlock(); bool ret = false; +#ifndef Q_OS_WINRT switch (WaitForSingleObject(d->handle, time)) { case WAIT_OBJECT_0: ret = true; @@ -561,6 +681,23 @@ bool QThread::wait(unsigned long time) default: break; } +#else // !Q_OS_WINRT + if (d->handle->joinable()) { + switch (WaitForSingleObjectEx(d->handle->native_handle(), time, FALSE)) { + case WAIT_OBJECT_0: + ret = true; + d->handle->join(); + break; + case WAIT_FAILED: + qErrnoWarning("QThread::wait: WaitForSingleObjectEx() failed"); + break; + case WAIT_ABANDONED: + case WAIT_TIMEOUT: + default: + break; + } + } +#endif // Q_OS_WINRT locker.mutex()->lock(); --d->waiters; @@ -572,7 +709,11 @@ bool QThread::wait(unsigned long time) } if (d->finished && !d->waiters) { +#ifndef Q_OS_WINRT CloseHandle(d->handle); +#else + delete d->handle; +#endif d->handle = 0; } @@ -590,13 +731,16 @@ void QThread::setTerminationEnabled(bool enabled) if (enabled && d->terminatePending) { QThreadPrivate::finish(thr, false); locker.unlock(); // don't leave the mutex locked! +#ifndef Q_OS_WINRT _endthreadex(0); +#endif } } // Caller must hold the mutex void QThreadPrivate::setPriority(QThread::Priority threadPriority) { +#ifndef Q_OS_WINRT // copied from start() with a few modifications: int prio; @@ -639,6 +783,12 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) if (!SetThreadPriority(handle, prio)) { qErrnoWarning("QThread::setPriority: Failed to set thread priority"); } +#else // !Q_OS_WINRT + if (priority != threadPriority) { + qWarning("QThread::setPriority: Failed to set thread priority (not implemented)"); + return; + } +#endif // Q_OS_WINRT } QT_END_NAMESPACE diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index fb1d1ee7cc..269f561a91 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -61,6 +61,7 @@ public: void run(); void registerThreadInactive(); + QWaitCondition runnableReady; QThreadPoolPrivate *manager; QRunnable *runnable; }; @@ -128,14 +129,13 @@ void QThreadPoolThread::run() // if too many threads are active, expire this thread bool expired = manager->tooManyThreadsActive(); if (!expired) { - ++manager->waitingThreads; + manager->waitingThreads.enqueue(this); registerThreadInactive(); // wait for work, exiting after the expiry timeout is reached - expired = !manager->runnableReady.wait(locker.mutex(), manager->expiryTimeout); + runnableReady.wait(locker.mutex(), manager->expiryTimeout); ++manager->activeThreads; - - if (expired) - --manager->waitingThreads; + if (manager->waitingThreads.removeOne(this)) + expired = true; } if (expired) { manager->expiredThreads.enqueue(this); @@ -160,7 +160,6 @@ QThreadPoolPrivate:: QThreadPoolPrivate() expiryTimeout(30000), maxThreadCount(qAbs(QThread::idealThreadCount())), reservedThreads(0), - waitingThreads(0), activeThreads(0) { } @@ -176,11 +175,10 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task) if (activeThreadCount() >= maxThreadCount) return false; - if (waitingThreads > 0) { + if (waitingThreads.count() > 0) { // recycle an available thread - --waitingThreads; enqueueTask(task); - runnableReady.wakeOne(); + waitingThreads.takeFirst()->runnableReady.wakeOne(); return true; } @@ -225,7 +223,7 @@ int QThreadPoolPrivate::activeThreadCount() const { return (allThreads.count() - expiredThreads.count() - - waitingThreads + - waitingThreads.count() + reservedThreads); } @@ -266,7 +264,6 @@ void QThreadPoolPrivate::reset() { QMutexLocker locker(&mutex); isExiting = true; - runnableReady.wakeAll(); while (!allThreads.empty()) { // move the contents of the set out so that we can iterate without the lock @@ -275,6 +272,7 @@ void QThreadPoolPrivate::reset() locker.unlock(); foreach (QThreadPoolThread *thread, allThreadsCopy) { + thread->runnableReady.wakeAll(); thread->wait(); delete thread; } @@ -283,7 +281,7 @@ void QThreadPoolPrivate::reset() // repeat until all newly arrived threads have also completed } - waitingThreads = 0; + waitingThreads.clear(); expiredThreads.clear(); isExiting = false; @@ -459,10 +457,8 @@ void QThreadPool::start(QRunnable *runnable, int priority) if (!d->tryStart(runnable)) { d->enqueueTask(runnable, priority); - if (d->waitingThreads > 0) { - --d->waitingThreads; - d->runnableReady.wakeOne(); - } + if (!d->waitingThreads.isEmpty()) + d->waitingThreads.takeFirst()->runnableReady.wakeOne(); } } diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h index ba77f7e57c..bd5f546fdb 100644 --- a/src/corelib/thread/qthreadpool_p.h +++ b/src/corelib/thread/qthreadpool_p.h @@ -87,8 +87,8 @@ public: void stealRunnable(QRunnable *); mutable QMutex mutex; - QWaitCondition runnableReady; QSet<QThreadPoolThread *> allThreads; + QQueue<QThreadPoolThread *> waitingThreads; QQueue<QThreadPoolThread *> expiredThreads; QList<QPair<QRunnable *, int> > queue; QWaitCondition noActiveThreads; @@ -97,7 +97,6 @@ public: int expiryTimeout; int maxThreadCount; int reservedThreads; - int waitingThreads; int activeThreads; }; diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h index 1468951373..ce073c21e9 100644 --- a/src/corelib/thread/qwaitcondition.h +++ b/src/corelib/thread/qwaitcondition.h @@ -84,9 +84,9 @@ public: bool wait(QMutex *mutex, unsigned long time = ULONG_MAX) { - Q_UNUSED(mutex); - Q_UNUSED(time); - return true; + Q_UNUSED(mutex); + Q_UNUSED(time); + return true; } void wakeOne() {} diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index 1cb1f82b03..f09667a364 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -64,7 +64,11 @@ class QWaitConditionEvent public: inline QWaitConditionEvent() : priority(0), wokenUp(false) { +#ifndef Q_OS_WINRT event = CreateEvent(NULL, TRUE, FALSE, NULL); +#else + event = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); +#endif } inline ~QWaitConditionEvent() { CloseHandle(event); } int priority; @@ -91,7 +95,9 @@ QWaitConditionEvent *QWaitConditionPrivate::pre() mtx.lock(); QWaitConditionEvent *wce = freeQueue.isEmpty() ? new QWaitConditionEvent : freeQueue.takeFirst(); +#ifndef Q_OS_WINRT wce->priority = GetThreadPriority(GetCurrentThread()); +#endif wce->wokenUp = false; // insert 'wce' into the queue (sorted by priority) @@ -111,7 +117,12 @@ bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, unsigned long time) { // wait for the event bool ret = false; +#ifndef Q_OS_WINRT switch (WaitForSingleObject(wce->event, time)) { +#else + switch (WaitForSingleObjectEx(wce->event, time, FALSE)) { +#endif + default: break; case WAIT_OBJECT_0: diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 13f0502b62..3c1ddd984a 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -17,8 +17,7 @@ HEADERS += thread/qmutex.h \ thread/qfuturesynchronizer.h \ thread/qfuturewatcher.h \ thread/qbasicatomic.h \ - thread/qgenericatomic.h \ - thread/qoldbasicatomic.h + thread/qgenericatomic.h # private headers HEADERS += thread/qmutex_p.h \ |