diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-07-01 11:05:26 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-07-01 11:05:26 +0200 |
commit | 0aa2d318b1524cdab42ab9988270779ddcc1922a (patch) | |
tree | 695c70702763ba2c66eb398ae9d545fc712a9e2d /src/corelib/thread | |
parent | 6251d4dafc86bcbec09d1962050af9924249d419 (diff) | |
parent | 49049d90470eb3e94bda77d19ab7f7c57a0bd57f (diff) | |
download | qtbase-0aa2d318b1524cdab42ab9988270779ddcc1922a.tar.gz |
Merge remote-tracking branch 'origin/5.5' into dev
Conflicts:
src/corelib/global/qglobal.cpp
src/corelib/global/qglobal.h
src/corelib/global/qsysinfo.h
src/corelib/global/qsystemdetection.h
src/corelib/kernel/qobjectdefs.h
src/plugins/plugins.pro
tests/auto/widgets/itemviews/qlistview/qlistview.pro
Change-Id: Ib55aa79d707c4c1453fb9d697f6cf92211ed665c
Diffstat (limited to 'src/corelib/thread')
-rw-r--r-- | src/corelib/thread/qthread_p.h | 9 | ||||
-rw-r--r-- | src/corelib/thread/qthread_win.cpp | 59 | ||||
-rw-r--r-- | src/corelib/thread/qthread_winrt.cpp | 450 | ||||
-rw-r--r-- | src/corelib/thread/thread.pri | 5 |
4 files changed, 51 insertions, 472 deletions
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 2008f76621..1ecd682ad1 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -171,19 +171,10 @@ public: #endif // Q_OS_UNIX #ifdef Q_OS_WIN -# ifndef Q_OS_WINRT static unsigned int __stdcall start(void *); static void finish(void *, bool lockAnyway=true); -# else - HRESULT start(ABI::Windows::Foundation::IAsyncAction *); - void finish(bool lockAnyway = true); -# endif -# ifndef Q_OS_WINRT Qt::HANDLE handle; -# else - ABI::Windows::Foundation::IAsyncAction *handle; -# endif unsigned int id; int waiters; bool terminationEnabled, terminatePending; diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index feb189bf45..c16a2e958c 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -32,7 +32,7 @@ ****************************************************************************/ //#define WINVER 0x0500 -#if (_WIN32_WINNT < 0x0400) +#if !defined Q_OS_WINRT && (_WIN32_WINNT < 0x0400) #define _WIN32_WINNT 0x0400 #endif @@ -46,18 +46,25 @@ #include <qpointer.h> #include <private/qcoreapplication_p.h> +#ifndef Q_OS_WINRT #include <private/qeventdispatcher_win_p.h> +#else +#include <private/qeventdispatcher_winrt_p.h> +#endif #include <qt_windows.h> +#ifndef Q_OS_WINRT #ifndef Q_OS_WINCE #ifndef _MT #define _MT -#endif +#endif // _MT #include <process.h> -#else +#else // !Q_OS_WINCE #include "qfunctions_wince.h" -#endif +#endif // Q_OS_WINCE +#else // !Q_OS_WINRT +#endif // Q_OS_WINRT #ifndef QT_NO_THREAD QT_BEGIN_NAMESPACE @@ -171,7 +178,11 @@ void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread) // Start watcher thread if it is not already running. if (qt_adopted_thread_watcher_id == 0) { if (qt_adopted_thread_wakeup == 0) { +#ifndef Q_OS_WINRT qt_adopted_thread_wakeup = CreateEvent(0, false, false, 0); +#else + qt_adopted_thread_wakeup = CreateEventEx(0, NULL, 0, EVENT_ALL_ACCESS); +#endif qt_adopted_thread_handles.prepend(qt_adopted_thread_wakeup); } @@ -210,13 +221,21 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID) // no need to loop, no timeout offset = 0; count = handlesCopy.count(); +#ifndef Q_OS_WINRT ret = WaitForMultipleObjects(handlesCopy.count(), handlesCopy.constData(), false, INFINITE); +#else + ret = WaitForMultipleObjectsEx(handlesCopy.count(), handlesCopy.constData(), false, INFINITE, false); +#endif } else { int loop = 0; do { offset = loop * MAXIMUM_WAIT_OBJECTS; count = qMin(handlesCopy.count() - offset, MAXIMUM_WAIT_OBJECTS); +#ifndef Q_OS_WINRT ret = WaitForMultipleObjects(count, handlesCopy.constData() + offset, false, 100); +#else + ret = WaitForMultipleObjectsEx(count, handlesCopy.constData() + offset, false, 100, false); +#endif loop = (loop + 1) % loops; } while (ret == WAIT_TIMEOUT); } @@ -263,7 +282,7 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID) return 0; } -#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) #ifndef Q_OS_WIN64 # define ULONG_PTR DWORD @@ -293,7 +312,7 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) { } } -#endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE +#endif // !QT_NO_DEBUG && Q_CC_MSVC && !Q_OS_WINCE && !Q_OS_WINRT /************************************************************************** ** QThreadPrivate @@ -303,7 +322,11 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) void QThreadPrivate::createEventDispatcher(QThreadData *data) { +#ifndef Q_OS_WINRT QEventDispatcherWin32 *theEventDispatcher = new QEventDispatcherWin32; +#else + QEventDispatcherWinRT *theEventDispatcher = new QEventDispatcherWinRT; +#endif data->eventDispatcher.storeRelease(theEventDispatcher); theEventDispatcher->startingUp(); } @@ -331,7 +354,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, @@ -396,13 +419,17 @@ 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; } void QThread::yieldCurrentThread() { -#ifndef Q_OS_WINCE +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) SwitchToThread(); #else ::Sleep(0); @@ -444,6 +471,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. @@ -456,6 +484,10 @@ void QThread::start(Priority priority) */ d->handle = (Qt::HANDLE) _beginthreadex(NULL, d->stackSize, QThreadPrivate::start, this, CREATE_SUSPENDED, &(d->id)); +#else // !Q_OS_WINRT + d->handle = (Qt::HANDLE) CreateThread(NULL, d->stackSize, (LPTHREAD_START_ROUTINE)QThreadPrivate::start, + this, CREATE_SUSPENDED, reinterpret_cast<LPDWORD>(&d->id)); +#endif // Q_OS_WINRT if (!d->handle) { qErrnoWarning(errno, "QThread::start: Failed to create thread"); @@ -521,7 +553,10 @@ void QThread::terminate() return; } + // Calling ExitThread() in setTerminationEnabled is all we can do on WinRT +#ifndef Q_OS_WINRT TerminateThread(d->handle, 0); +#endif QThreadPrivate::finish(this, false); } @@ -541,7 +576,11 @@ bool QThread::wait(unsigned long time) locker.mutex()->unlock(); bool ret = false; +#ifndef Q_OS_WINRT switch (WaitForSingleObject(d->handle, time)) { +#else + switch (WaitForSingleObjectEx(d->handle, time, false)) { +#endif case WAIT_OBJECT_0: ret = true; break; @@ -582,7 +621,11 @@ 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); +#else + ExitThread(0); +#endif } } diff --git a/src/corelib/thread/qthread_winrt.cpp b/src/corelib/thread/qthread_winrt.cpp deleted file mode 100644 index f4a7a662cb..0000000000 --- a/src/corelib/thread/qthread_winrt.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qthread.h" -#include "qthread_p.h" -#include "qthreadstorage.h" - -#include <QtCore/QElapsedTimer> -#include <QtCore/QUuid> -#include <QtCore/qt_windows.h> -#include <QtCore/qfunctions_winrt.h> -#include <QtCore/private/qcoreapplication_p.h> -#include <QtCore/private/qeventdispatcher_winrt_p.h> - -#include <wrl.h> -#include <windows.system.threading.h> -#include <windows.system.threading.core.h> -using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; -using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::System::Threading; -using namespace ABI::Windows::System::Threading::Core; - -#ifndef QT_NO_THREAD -QT_BEGIN_NAMESPACE - -static WorkItemPriority nativePriority(QThread::Priority priority) -{ - switch (priority) { - default: - case QThread::NormalPriority: - return WorkItemPriority_Normal; - case QThread::IdlePriority: - case QThread::LowestPriority: - case QThread::LowPriority: - return WorkItemPriority_Low; - case QThread::HighPriority: - case QThread::HighestPriority: - case QThread::TimeCriticalPriority: - return WorkItemPriority_High; - } -} - -class QWinRTThreadGlobal -{ -public: - QWinRTThreadGlobal() - { - HRESULT hr; - - hr = RoGetActivationFactory( - HString::MakeReference(RuntimeClass_Windows_System_Threading_Core_PreallocatedWorkItem).Get(), - IID_PPV_ARGS(&workItemFactory)); - Q_ASSERT_SUCCEEDED(hr); - - hr = RoGetActivationFactory( - HString::MakeReference(RuntimeClass_Windows_System_Threading_Core_SignalNotifier).Get(), - IID_PPV_ARGS(¬ifierFactory)); - Q_ASSERT_SUCCEEDED(hr); - - QString eventName = QUuid::createUuid().toString(); - dispatchEvent = CreateEventEx(NULL, reinterpret_cast<LPCWSTR>(eventName.utf16()), 0, EVENT_ALL_ACCESS); - - hr = notifierFactory->AttachToEvent( - HStringReference(reinterpret_cast<LPCWSTR>(eventName.utf16())).Get(), - Callback<ISignalHandler>(this, &QWinRTThreadGlobal::dispatch).Get(), ¬ifier); - Q_ASSERT_SUCCEEDED(hr); - hr = notifier->Enable(); - Q_ASSERT_SUCCEEDED(hr); - } - - ~QWinRTThreadGlobal() - { - CloseHandle(dispatchEvent); - } - - void dispatch() - { - SetEvent(dispatchEvent); - } - - void push(QThreadPrivate *d) - { - threads.append(d); - } - -private: - HRESULT dispatch(ISignalNotifier *notifier, boolean timedOut) - { - Q_UNUSED(timedOut); - notifier->Enable(); - if (threads.isEmpty()) - return S_OK; - - QThreadPrivate *thread = threads.takeFirst(); - ComPtr<IPreallocatedWorkItem> workItem; - HRESULT hr = workItemFactory->CreateWorkItemWithPriority( - Callback<IWorkItemHandler>(thread, &QThreadPrivate::start).Get(), - nativePriority(thread->priority), &workItem); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to create thread work item"); - thread->finish(); - return hr; - } - - hr = workItem->RunAsync(&thread->handle); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to run work item"); - thread->finish(); - return hr; - } - - return S_OK; - } - - HANDLE dispatchEvent; - ComPtr<ISignalNotifier> notifier; - ComPtr<ISignalNotifierStatics> notifierFactory; - ComPtr<IPreallocatedWorkItemFactory> workItemFactory; - - QList<QThreadPrivate *> threads; -}; -Q_GLOBAL_STATIC(QWinRTThreadGlobal, g) - -/************************************************************************** - ** QThreadData - *************************************************************************/ - -__declspec(thread) static QThreadData *qt_current_thread_data = 0; - -void QThreadData::clearCurrentThreadData() -{ - qt_current_thread_data = 0; -} - -QThreadData *QThreadData::current(bool createIfNecessary) -{ - static bool winmainThread = true; - QThreadData *threadData = qt_current_thread_data; - if (!threadData && createIfNecessary) { - threadData = new QThreadData; - // This needs to be called prior to new AdoptedThread() to - // avoid recursion. - qt_current_thread_data = threadData; - QT_TRY { - threadData->thread = new QAdoptedThread(threadData); - } QT_CATCH(...) { - qt_current_thread_data = 0; - threadData->deref(); - threadData = 0; - QT_RETHROW; - } - threadData->deref(); - threadData->isAdopted = true; - threadData->threadId = reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId()); - - if (!QCoreApplicationPrivate::theMainThread && !winmainThread) - QCoreApplicationPrivate::theMainThread = threadData->thread; - - if (winmainThread) { - g->dispatch(); - threadData->thread->d_func()->createEventDispatcher(threadData); - winmainThread = false; - } - } - - return threadData; -} - -void QAdoptedThread::init() -{ - Q_D(QThread); - - d->handle = Q_NULLPTR; - d->id = 0; -} - -/************************************************************************** - ** QThreadPrivate - *************************************************************************/ - -#endif // QT_NO_THREAD - -void QThreadPrivate::createEventDispatcher(QThreadData *data) -{ - QEventDispatcherWinRT *eventDispatcher = new QEventDispatcherWinRT; - data->eventDispatcher.storeRelease(eventDispatcher); - eventDispatcher->startingUp(); -} - -#ifndef QT_NO_THREAD - -HRESULT QThreadPrivate::start(IAsyncAction *) -{ - Q_Q(QThread); - - qt_current_thread_data = data; - id = GetCurrentThreadId(); - data->threadId = reinterpret_cast<Qt::HANDLE>(id); - QThread::setTerminationEnabled(false); - - { - QMutexLocker locker(&mutex); - data->quitNow = exited; - } - - if (data->eventDispatcher.load()) - data->eventDispatcher.load()->startingUp(); - else - createEventDispatcher(data); - - running = true; - emit q->started(QThread::QPrivateSignal()); - - QThread::setTerminationEnabled(true); - - q->run(); - - finish(); - - return S_OK; -} - -void QThreadPrivate::finish(bool lockAnyway) -{ - Q_Q(QThread); - - QMutexLocker locker(lockAnyway ? &mutex : 0); - isInFinish = true; - priority = QThread::InheritPriority; - void **tls_data = reinterpret_cast<void **>(&data->tls); - locker.unlock(); - emit q->finished(QThread::QPrivateSignal()); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); - QThreadStorageData::finish(tls_data); - locker.relock(); - - QAbstractEventDispatcher *eventDispatcher = data->eventDispatcher.load(); - if (eventDispatcher) { - data->eventDispatcher = 0; - locker.unlock(); - eventDispatcher->closingDown(); - delete eventDispatcher; - locker.relock(); - } - - running = false; - finished = true; - isInFinish = false; - interruptionRequested = false; - - if (!waiters) { - if (handle) - handle->Release(); - handle = Q_NULLPTR; - } - - id = 0; -} - -/************************************************************************** - ** QThread - *************************************************************************/ - -Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW -{ - return reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId()); -} - -int QThread::idealThreadCount() Q_DECL_NOTHROW -{ - SYSTEM_INFO sysinfo; - GetNativeSystemInfo(&sysinfo); - return sysinfo.dwNumberOfProcessors; -} - -void QThread::yieldCurrentThread() -{ - msleep(1); -} - -void QThread::sleep(unsigned long secs) -{ - msleep(secs * 1000); -} - -void QThread::msleep(unsigned long msecs) -{ - WaitForSingleObjectEx(GetCurrentThread(), msecs, FALSE); -} - -void QThread::usleep(unsigned long usecs) -{ - msleep((usecs / 1000) + 1); -} - -void QThread::start(Priority priority) -{ - Q_D(QThread); - QMutexLocker locker(&d->mutex); - - if (d->isInFinish) { - locker.unlock(); - wait(); - locker.relock(); - } - - if (d->running) - return; - - d->finished = false; - d->exited = false; - d->returnCode = 0; - d->interruptionRequested = false; - d->priority = priority == QThread::InheritPriority ? currentThread()->priority() : priority; - g->push(d); - g->dispatch(); - - locker.unlock(); - while (!d->running && !d->finished) { - QAbstractEventDispatcher *eventDispatcher = QThread::currentThread()->eventDispatcher(); - if (eventDispatcher) - eventDispatcher->processEvents(QEventLoop::AllEvents); - else - yieldCurrentThread(); - } -} - -void QThread::terminate() -{ - Q_D(QThread); - QMutexLocker locker(&d->mutex); - if (!d->running) - return; - if (!d->terminationEnabled) { - d->terminatePending = true; - return; - } - - if (d->handle) { - ComPtr<IAsyncInfo> info; - HRESULT hr = d->handle->QueryInterface(IID_PPV_ARGS(&info)); - Q_ASSERT_SUCCEEDED(hr); - hr = info->Cancel(); - if (FAILED(hr)) - qErrnoWarning(hr, "Failed to cancel thread action"); - } - - d->finish(false); -} - -bool QThread::wait(unsigned long time) -{ - Q_D(QThread); - QMutexLocker locker(&d->mutex); - - if (d->id == GetCurrentThreadId()) { - qWarning("QThread::wait: Thread tried to wait on itself"); - return false; - } - if (d->finished || !d->running) - return true; - - ++d->waiters; - locker.mutex()->unlock(); - - // Alternatively, we could check the handle - bool ret = false; - if (!d->finished) { - QElapsedTimer timer; - timer.start(); - while (timer.elapsed() < time && !d->finished) - yieldCurrentThread(); - - ret = d->finished; - } - - locker.mutex()->lock(); - --d->waiters; - - if (ret && !d->finished) { - // thread was terminated by someone else - - d->finish(false); - } - - if (d->finished && !d->waiters) { - if (d->handle) - d->handle->Release(); - d->handle = Q_NULLPTR; - } - - return ret; -} - -void QThread::setTerminationEnabled(bool enabled) -{ - QThread *thr = currentThread(); - Q_ASSERT_X(thr != 0, "QThread::setTerminationEnabled()", - "Current thread was not started with QThread."); - QThreadPrivate *d = thr->d_func(); - QMutexLocker locker(&d->mutex); - d->terminationEnabled = enabled; - if (enabled && d->terminatePending) { - d->finish(false); - locker.unlock(); // don't leave the mutex locked! - } -} - -// Caller must hold the mutex -void QThreadPrivate::setPriority(QThread::Priority threadPriority) -{ - if (running) - qWarning("WinRT threads can't change priority while running."); - - priority = threadPriority; -} - -QT_END_NAMESPACE -#endif // QT_NO_THREAD diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 2e027c8e21..3c1ddd984a 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -50,11 +50,6 @@ win32:SOURCES += thread/qmutex_win.cpp \ thread/qthread_win.cpp \ thread/qwaitcondition_win.cpp -winrt { - SOURCES -= thread/qthread_win.cpp - SOURCES += thread/qthread_winrt.cpp -} - integrity:SOURCES += thread/qmutex_unix.cpp \ thread/qthread_unix.cpp \ thread/qwaitcondition_unix.cpp |