From 99b03be63de497bebbc26fcb2a564f1938493ef0 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 3 Nov 2013 01:00:57 -0500 Subject: [PATCH] Add threading debug spew when QT_DEBUG is set --- src/kernel/qeventloop_unix_glib.cpp | 4 ++-- src/kernel/qobject.cpp | 20 ++++++++++++++++---- src/kernel/qthread.cpp | 23 +++++++++++++++++++++++ src/kernel/qthread.h | 5 ++++- src/kernel/qthread_unix.cpp | 8 +++++++- src/tools/qthreadinstance_p.h | 1 + tutorial/t15/main.cpp | 10 +++++----- 7 files changed, 58 insertions(+), 13 deletions(-) diff --git a/src/kernel/qeventloop_unix_glib.cpp b/src/kernel/qeventloop_unix_glib.cpp index 6924fcd..feff675 100644 --- a/src/kernel/qeventloop_unix_glib.cpp +++ b/src/kernel/qeventloop_unix_glib.cpp @@ -688,7 +688,7 @@ int QEventLoop::activateTimers() QTimerEvent e( t->id ); #if defined(QT_THREAD_SUPPORT) // Be careful...the current thread may not be the target object's thread! - if ((!t->obj) || (t->obj && (t->obj->contextThreadObject() == QThread::currentThreadObject()))) { + if ((!t->obj) || (QThread::currentThreadObject()->threadPostedEventsDisabled()) || (t->obj && (t->obj->contextThreadObject() == QThread::currentThreadObject()))) { QApplication::sendEvent( t->obj, &e ); // send event } else { @@ -731,7 +731,7 @@ int QEventLoop::activateSocketNotifiers() sn->pending = FALSE; #if defined(QT_THREAD_SUPPORT) // Be careful...the current thread may not be the target object's thread! - if ((!sn->obj) || (sn->obj && (sn->obj->contextThreadObject() == QThread::currentThreadObject()))) { + if ((!sn->obj) || (QThread::currentThreadObject()->threadPostedEventsDisabled()) || (sn->obj && (sn->obj->contextThreadObject() == QThread::currentThreadObject()))) { QApplication::sendEvent( sn->obj, &event ); // send event } else { diff --git a/src/kernel/qobject.cpp b/src/kernel/qobject.cpp index 9e5ac8e..247db41 100644 --- a/src/kernel/qobject.cpp +++ b/src/kernel/qobject.cpp @@ -2727,7 +2727,7 @@ void QObject::activate_signal( QConnectionList *clist, QUObject *o ) sol->currentSender = this; } if ( c->memberType() == QSIGNAL_CODE ) { - if ((d->disableThreadPostedEvents) || (object->d->ownThread == currentThread)) { + if ((d->disableThreadPostedEvents) || (object->d->disableThreadPostedEvents) || (currentThread->threadPostedEventsDisabled()) || (object->d->ownThread == currentThread)) { #ifdef QT_THREAD_SUPPORT sol->listMutex->unlock(); #endif // QT_THREAD_SUPPORT @@ -2738,12 +2738,15 @@ void QObject::activate_signal( QConnectionList *clist, QUObject *o ) } else { if (object->d->ownThread && !object->d->ownThread->finished()) { +#ifdef QT_DEBUG + qDebug("QObject::activate_signal: Emitting cross-thread signal from object %p (member %d receiver %p) (1)\n\r", this, c->member(), object); +#endif // QT_DEBUG QApplication::postEvent(object, new QMetaCallEvent(c->member(), this, deepCopyQUObjectArray(o), QMetaCallEvent::MetaCallEmit)); } } } else { - if ((d->disableThreadPostedEvents) || (object->d->ownThread == currentThread)) { + if ((d->disableThreadPostedEvents) || (object->d->disableThreadPostedEvents) || (currentThread->threadPostedEventsDisabled()) || (object->d->ownThread == currentThread)) { #ifdef QT_THREAD_SUPPORT sol->listMutex->unlock(); #endif // QT_THREAD_SUPPORT @@ -2754,6 +2757,9 @@ void QObject::activate_signal( QConnectionList *clist, QUObject *o ) } else { if (object->d->ownThread && !object->d->ownThread->finished()) { +#ifdef QT_DEBUG + qDebug("QObject::activate_signal: Invoking cross-thread method from object %p (member %d receiver %p) (1)\n\r", this, c->member(), object); +#endif // QT_DEBUG QApplication::postEvent(object, new QMetaCallEvent(c->member(), this, deepCopyQUObjectArray(o), QMetaCallEvent::MetaCallInvoke)); } } @@ -2788,7 +2794,7 @@ void QObject::activate_signal( QConnectionList *clist, QUObject *o ) sol->currentSender = this; } if ( c->memberType() == QSIGNAL_CODE ) { - if ((d->disableThreadPostedEvents) || (object->d->ownThread == currentThread)) { + if ((d->disableThreadPostedEvents) || (object->d->disableThreadPostedEvents) || (currentThread->threadPostedEventsDisabled()) || (object->d->ownThread == currentThread)) { #ifdef QT_THREAD_SUPPORT sol->listMutex->unlock(); #endif // QT_THREAD_SUPPORT @@ -2799,12 +2805,15 @@ void QObject::activate_signal( QConnectionList *clist, QUObject *o ) } else { if (object->d->ownThread && !object->d->ownThread->finished()) { +#ifdef QT_DEBUG + qDebug("QObject::activate_signal: Emitting cross-thread signal from object %p (member %d receiver %p) (2)\n\r", this, c->member(), object); +#endif // QT_DEBUG QApplication::postEvent(object, new QMetaCallEvent(c->member(), this, deepCopyQUObjectArray(o), QMetaCallEvent::MetaCallEmit)); } } } else { - if ((d->disableThreadPostedEvents) || (object->d->ownThread == currentThread)) { + if ((d->disableThreadPostedEvents) || (object->d->disableThreadPostedEvents) || (currentThread->threadPostedEventsDisabled()) || (object->d->ownThread == currentThread)) { #ifdef QT_THREAD_SUPPORT sol->listMutex->unlock(); #endif // QT_THREAD_SUPPORT @@ -2815,6 +2824,9 @@ void QObject::activate_signal( QConnectionList *clist, QUObject *o ) } else { if (object->d->ownThread && !object->d->ownThread->finished()) { +#ifdef QT_DEBUG + qDebug("QObject::activate_signal: Invoking cross-thread method from object %p (member %d receiver %p) (2)\n\r", this, c->member(), object); +#endif // QT_DEBUG QApplication::postEvent(object, new QMetaCallEvent(c->member(), this, deepCopyQUObjectArray(o), QMetaCallEvent::MetaCallInvoke)); } } diff --git a/src/kernel/qthread.cpp b/src/kernel/qthread.cpp index 93fc3f2..4eeb823 100644 --- a/src/kernel/qthread.cpp +++ b/src/kernel/qthread.cpp @@ -223,6 +223,29 @@ bool QThread::running() const return d->running; } +/*! + Changes the way cross thread signals are handled + If disable is FALSE, signals emitted from this thread will be + posted to any other connected threads' event loops (default). + + If disable is TRUE, calls to emit from this thread + will immediately execute slots in another thread. + This mode of operation is inherently unsafe and is provided + solely to support thread management by a third party application. + */ +void QThread::setThreadPostedEventsDisabled(bool disable) +{ + d->disableThreadPostedEvents = disable; +} + +/*! + Returns TRUE if thread posted events are disabled, FALSE if not + */ +bool QThread::threadPostedEventsDisabled() const +{ + return d->disableThreadPostedEvents; +} + /*! \fn void QThread::run() diff --git a/src/kernel/qthread.h b/src/kernel/qthread.h index 80448a0..675e3a3 100644 --- a/src/kernel/qthread.h +++ b/src/kernel/qthread.h @@ -113,9 +113,12 @@ public: CleanupMergeObjects }; - CleanupType cleanupType(); + CleanupType cleanupType() const; void setCleanupType(CleanupType); + bool threadPostedEventsDisabled() const; + void setThreadPostedEventsDisabled(bool); + protected: virtual void run() = 0; diff --git a/src/kernel/qthread_unix.cpp b/src/kernel/qthread_unix.cpp index a48468b..530d401 100644 --- a/src/kernel/qthread_unix.cpp +++ b/src/kernel/qthread_unix.cpp @@ -105,6 +105,7 @@ void QThreadInstance::init(unsigned int stackSize) finished = FALSE; running = FALSE; orphan = FALSE; + disableThreadPostedEvents = FALSE; pthread_cond_init(&thread_done, NULL); thread_id = 0; @@ -130,6 +131,9 @@ void *QThreadInstance::start( void *_arg ) ((QThreadInstance*)arg[1])->thread_id = pthread_self(); #endif // QT_USE_GLIBMAINLOOP +#ifdef QT_DEBUG + qDebug("QThreadInstance::start: Setting thread storage to %p\n\r", (QThread *) arg[0]); +#endif // QT_DEBUG setCurrentThread( (QThread *) arg[0] ); pthread_cleanup_push( QThreadInstance::finish, arg[1] ); @@ -152,6 +156,8 @@ void QThreadInstance::finish( void * ) return; } + qDebug("QThreadInstance::finish: In QThreadInstance::finish for thread %p\n\r", (QThread*)d->args[0]); + QApplication::threadTerminationHandler((QThread*)d->args[0]); QMutexLocker locker( d->mutex() ); @@ -510,7 +516,7 @@ bool QThread::wait( unsigned long time ) \sa CleanupType */ -QThread::CleanupType QThread::cleanupType() { +QThread::CleanupType QThread::cleanupType() const { return (QThread::CleanupType)d->cleanupType; } diff --git a/src/tools/qthreadinstance_p.h b/src/tools/qthreadinstance_p.h index 34550a8..87dbe6c 100644 --- a/src/tools/qthreadinstance_p.h +++ b/src/tools/qthreadinstance_p.h @@ -102,6 +102,7 @@ public: QEventLoop* eventLoop; int cleanupType; + bool disableThreadPostedEvents : 1; }; #endif // QT_THREAD_SUPPORT diff --git a/tutorial/t15/main.cpp b/tutorial/t15/main.cpp index 61febaa..72736df 100644 --- a/tutorial/t15/main.cpp +++ b/tutorial/t15/main.cpp @@ -57,11 +57,11 @@ void MainObject::buttonClicked() eventLoop->exit(0); } -#define SET_UP_WORKER(x, y, z) \ - WorkerObject x; \ - x.threadFriendlyName = y; \ - x.moveToThread(&z); \ - QObject::connect(&x, SIGNAL(displayMessage(QString,QString)), &mainobject, SLOT(emitMessage(QString,QString))); \ +#define SET_UP_WORKER(x, y, z) \ + WorkerObject x; \ + x.threadFriendlyName = y; \ + x.moveToThread(&z); \ + QObject::connect(&x, SIGNAL(displayMessage(QString,QString)), &mainobject, SLOT(emitMessage(QString,QString))); \ QTimer::singleShot(0, &x, SLOT(run())); int main( int argc, char **argv )