diff options
Diffstat (limited to 'src/corelib/thread/qthread_winrt.cpp')
-rw-r--r-- | src/corelib/thread/qthread_winrt.cpp | 450 |
1 files changed, 0 insertions, 450 deletions
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 |