threading support for winrt
Change-Id: Ife296e15ddf727c3f53ab3d3d84634b5c7bbf85c Done-with: Maurice Kalinowski Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
9260a3917a
commit
d7af71b318
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -40,7 +40,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
//#define WINVER 0x0500
|
||||
#if _WIN32_WINNT < 0x0400
|
||||
#if (_WIN32_WINNT < 0x0400) && !defined(Q_OS_WINRT)
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#endif
|
||||
|
||||
@ -58,6 +58,9 @@
|
||||
|
||||
#include <qt_windows.h>
|
||||
|
||||
#ifdef Q_OS_WINRT
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
#ifndef Q_OS_WINCE
|
||||
#ifndef _MT
|
||||
@ -71,6 +74,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 +96,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 +160,9 @@ QThreadData *QThreadData::current()
|
||||
|
||||
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 +177,7 @@ QThreadData *QThreadData::current()
|
||||
realHandle = reinterpret_cast<HANDLE>(GetCurrentThreadId());
|
||||
#endif
|
||||
qt_watch_adopted_thread(realHandle, threadData->thread);
|
||||
#endif // !Q_OS_WINRT
|
||||
}
|
||||
}
|
||||
return threadData;
|
||||
@ -145,10 +185,16 @@ QThreadData *QThreadData::current()
|
||||
|
||||
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;
|
||||
@ -297,6 +343,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
|
||||
@ -334,7 +381,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,
|
||||
@ -380,11 +427,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
|
||||
|
||||
}
|
||||
|
||||
@ -400,10 +456,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
|
||||
@ -427,7 +488,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)
|
||||
{
|
||||
@ -449,6 +531,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.
|
||||
@ -513,6 +596,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()
|
||||
@ -525,7 +625,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);
|
||||
}
|
||||
|
||||
@ -534,7 +641,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;
|
||||
}
|
||||
@ -545,6 +656,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;
|
||||
@ -557,6 +669,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;
|
||||
@ -568,7 +697,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;
|
||||
}
|
||||
|
||||
@ -586,13 +719,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;
|
||||
@ -635,6 +771,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
|
||||
|
@ -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:
|
||||
|
@ -55,6 +55,8 @@
|
||||
#endif
|
||||
#if defined(Q_OS_WINCE)
|
||||
#include <windows.h>
|
||||
#elif defined(Q_OS_WINRT)
|
||||
#include <thread>
|
||||
#elif defined(Q_OS_WIN)
|
||||
#include <process.h>
|
||||
#include <windows.h>
|
||||
@ -460,6 +462,10 @@ void tst_QThread::start()
|
||||
QVERIFY(!thread.isFinished());
|
||||
QVERIFY(!thread.isRunning());
|
||||
QMutexLocker locker(&thread.mutex);
|
||||
#ifdef Q_OS_WINRT
|
||||
if (priorities[i] != QThread::NormalPriority && priorities[i] != QThread::InheritPriority)
|
||||
QTest::ignoreMessage(QtWarningMsg, "QThread::start: Failed to set thread priority (not implemented)");
|
||||
#endif
|
||||
thread.start(priorities[i]);
|
||||
QVERIFY(thread.isRunning());
|
||||
QVERIFY(!thread.isFinished());
|
||||
@ -630,6 +636,8 @@ void noop(void*) { }
|
||||
|
||||
#if defined Q_OS_UNIX
|
||||
typedef pthread_t ThreadHandle;
|
||||
#elif defined Q_OS_WINRT
|
||||
typedef std::thread ThreadHandle;
|
||||
#elif defined Q_OS_WIN
|
||||
typedef HANDLE ThreadHandle;
|
||||
#endif
|
||||
@ -671,6 +679,8 @@ void NativeThreadWrapper::start(FunctionPointer functionPointer, void *data)
|
||||
#if defined Q_OS_UNIX
|
||||
const int state = pthread_create(&nativeThreadHandle, 0, NativeThreadWrapper::runUnix, this);
|
||||
Q_UNUSED(state);
|
||||
#elif defined(Q_OS_WINRT)
|
||||
nativeThreadHandle = std::thread(NativeThreadWrapper::runWin, this);
|
||||
#elif defined(Q_OS_WINCE)
|
||||
nativeThreadHandle = CreateThread(NULL, 0 , (LPTHREAD_START_ROUTINE)NativeThreadWrapper::runWin , this, 0, NULL);
|
||||
#elif defined Q_OS_WIN
|
||||
@ -690,6 +700,8 @@ void NativeThreadWrapper::join()
|
||||
{
|
||||
#if defined Q_OS_UNIX
|
||||
pthread_join(nativeThreadHandle, 0);
|
||||
#elif defined Q_OS_WINRT
|
||||
nativeThreadHandle.join();
|
||||
#elif defined Q_OS_WIN
|
||||
WaitForSingleObject(nativeThreadHandle, INFINITE);
|
||||
CloseHandle(nativeThreadHandle);
|
||||
|
Loading…
x
Reference in New Issue
Block a user