diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2019-06-03 14:00:07 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2019-06-03 14:01:18 +0300 |
commit | 01cfc8025119609803b3fc00b1e8ca5bc56e84d0 (patch) | |
tree | c41480bbb06377f3a79d13c465a53435cccb9de4 /src/Runtime/ogl-runtime/src/foundation/windows/Qt3DSWindowsThread.cpp | |
parent | c36739204786bd90df6e2ef5a8be78c980240bdd (diff) | |
parent | 089d283afb8cde5024e60c29eeeeefc5c3c80543 (diff) |
Merge branch '2.4'
Change-Id: Ib7de8e52a477c06599ced87bb973a5abd25549c4
Diffstat (limited to 'src/Runtime/ogl-runtime/src/foundation/windows/Qt3DSWindowsThread.cpp')
-rw-r--r-- | src/Runtime/ogl-runtime/src/foundation/windows/Qt3DSWindowsThread.cpp | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/src/Runtime/ogl-runtime/src/foundation/windows/Qt3DSWindowsThread.cpp b/src/Runtime/ogl-runtime/src/foundation/windows/Qt3DSWindowsThread.cpp new file mode 100644 index 00000000..3a30de8c --- /dev/null +++ b/src/Runtime/ogl-runtime/src/foundation/windows/Qt3DSWindowsThread.cpp @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2012 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "foundation/windows/Qt3DSWindowsInclude.h" +#include "foundation/Qt3DSFoundation.h" +#include "foundation/Qt3DSThread.h" +#include "foundation/Qt3DSAssert.h" +#include "foundation/Qt3DSBroadcastingAllocator.h" + +// an exception for setting the thread name in microsoft debuggers +#define QT3DS_MS_VC_EXCEPTION 0x406D1388 + +namespace qt3ds { +namespace foundation { + +// struct for naming a thread in the debugger +#pragma pack(push, 8) + + typedef struct tagTHREADNAME_INFO + { + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. + } THREADNAME_INFO; + +#pragma pack(pop) + + namespace { + + DWORD WINAPI NVThreadStart(LPVOID arg) + { + ((Thread *)arg)->execute(); + return 0; + } + } + + class ThreadImpl + { + public: + enum State { NotStarted, Started, Stopped }; + ThreadImpl(NVFoundationBase &foundation) + : mFoundation(foundation) + { + } + NVFoundationBase &mFoundation; + HANDLE thread; + LONG quitNow; // Should be 32bit aligned on SMP systems. + State state; + DWORD threadID; + + Thread::ExecuteFn fn; + void *arg; + }; + + Thread::Id Thread::getId() { return static_cast<Id>(GetCurrentThreadId()); } + + Thread::Thread(NVFoundationBase &foundation) + { + mImpl = (ThreadImpl *)QT3DS_NEW(foundation.getAllocator(), ThreadImpl)(foundation); + mImpl->thread = NULL; + mImpl->state = ThreadImpl::NotStarted; + mImpl->quitNow = 0; + } + + Thread::Thread(NVFoundationBase &foundation, ExecuteFn fn, void *arg) + { + mImpl = (ThreadImpl *)QT3DS_NEW(foundation.getAllocator(), ThreadImpl)(foundation); + mImpl->thread = NULL; + mImpl->state = ThreadImpl::NotStarted; + mImpl->quitNow = 0; + mImpl->fn = fn; + mImpl->arg = arg; + + start(0); + } + + Thread::~Thread() + { + if (mImpl->state == ThreadImpl::Started) + kill(); + CloseHandle(mImpl->thread); + QT3DS_FREE(mImpl->mFoundation.getAllocator(), mImpl); + } + + void Thread::start(QT3DSU32 stackSize) + { + if (mImpl->state != ThreadImpl::NotStarted) + return; + mImpl->state = ThreadImpl::Started; + + mImpl->thread = + CreateThread(NULL, stackSize, NVThreadStart, (LPVOID)this, 0, &mImpl->threadID); + } + + void Thread::signalQuit() { InterlockedIncrement(&(mImpl->quitNow)); } + + bool Thread::waitForQuit() + { + if (mImpl->state == ThreadImpl::NotStarted) + return false; + + WaitForSingleObject(mImpl->thread, INFINITE); + return true; + } + + bool Thread::quitIsSignalled() + { + return InterlockedCompareExchange(&(mImpl->quitNow), 0, 0) != 0; + } + + void Thread::quit() + { + mImpl->state = ThreadImpl::Stopped; + ExitThread(0); + } + + void Thread::kill() + { + if (mImpl->state == ThreadImpl::Started) + TerminateThread(mImpl->thread, 0); + mImpl->state = ThreadImpl::Stopped; + } + + void Thread::sleep(QT3DSU32 ms) { Sleep(ms); } + + void Thread::yield() { SwitchToThread(); } + + void Thread::execute(void) { (*mImpl->fn)(mImpl->arg); } + + QT3DSU32 Thread::setAffinityMask(QT3DSU32 mask) + { + return mask ? (QT3DSU32)SetThreadAffinityMask(mImpl->thread, mask) : 0; + } + + void Thread::setName(const char *name) + { + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name; + info.dwThreadID = mImpl->threadID; + info.dwFlags = 0; + +#ifdef QT3DS_VC + // C++ Exceptions are disabled for this project, but SEH is not (and cannot be) + // http://stackoverflow.com/questions/943087/what-exactly-will-happen-if-i-disable-c-exceptions-in-a-project + __try { + RaiseException(QT3DS_MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), + (ULONG_PTR *)&info); + } __except (EXCEPTION_EXECUTE_HANDLER) { + // this runs if not attached to a debugger (thus not really naming the thread) + } +#else + RaiseException(QT3DS_MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), + (ULONG_PTR *)&info); +#endif + } + + void Thread::setPriority(ThreadPriority::Enum prio) + { + switch (prio) { + case ThreadPriority::eHIGH: + SetThreadPriority(mImpl->thread, THREAD_PRIORITY_HIGHEST); + break; + case ThreadPriority::eABOVE_NORMAL: + SetThreadPriority(mImpl->thread, THREAD_PRIORITY_ABOVE_NORMAL); + break; + case ThreadPriority::eNORMAL: + SetThreadPriority(mImpl->thread, THREAD_PRIORITY_NORMAL); + break; + case ThreadPriority::eBELOW_NORMAL: + SetThreadPriority(mImpl->thread, THREAD_PRIORITY_BELOW_NORMAL); + break; + case ThreadPriority::eLOW: + SetThreadPriority(mImpl->thread, THREAD_PRIORITY_LOWEST); + break; + default: + break; + } + } + + ThreadPriority::Enum Thread::getPriority(Id threadId) + { + ThreadPriority::Enum retval = ThreadPriority::eLOW; + int priority = GetThreadPriority((HANDLE)threadId); + StaticAssert<(THREAD_PRIORITY_HIGHEST > THREAD_PRIORITY_ABOVE_NORMAL)>::valid_expression(); + if (priority >= THREAD_PRIORITY_HIGHEST) + retval = ThreadPriority::eHIGH; + else if (priority >= THREAD_PRIORITY_ABOVE_NORMAL) + retval = ThreadPriority::eABOVE_NORMAL; + else if (priority >= THREAD_PRIORITY_NORMAL) + retval = ThreadPriority::eNORMAL; + else if (priority >= THREAD_PRIORITY_BELOW_NORMAL) + retval = ThreadPriority::eBELOW_NORMAL; + return retval; + } + + QT3DSU32 TlsAlloc() + { + DWORD rv = ::TlsAlloc(); + QT3DS_ASSERT(rv != TLS_OUT_OF_INDEXES); + return (QT3DSU32)rv; + } + + void TlsFree(QT3DSU32 index) { ::TlsFree(index); } + + void *TlsGet(QT3DSU32 index) { return ::TlsGetValue(index); } + + QT3DSU32 TlsSet(QT3DSU32 index, void *value) { return ::TlsSetValue(index, value); } + + const QT3DSU32 Thread::DEFAULT_STACK_SIZE = 1048576; + +} // namespace foundation +} // namespace qt3ds |