diff --git a/src/kernel/ntqthread.h b/src/kernel/ntqthread.h index 5a832710..04684ac0 100644 --- a/src/kernel/ntqthread.h +++ b/src/kernel/ntqthread.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/qeventloop_unix_glib.cpp b/src/kernel/qeventloop_unix_glib.cpp index 1decd8f1..795dc9ba 100644 --- a/src/kernel/qeventloop_unix_glib.cpp +++ b/src/kernel/qeventloop_unix_glib.cpp @@ -688,7 +688,7 @@ int TQEventLoop::activateTimers() TQTimerEvent 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() == TQThread::currentThreadObject()))) { + if ((!t->obj) || (TQThread::currentThreadObject()->threadPostedEventsDisabled()) || (t->obj && (t->obj->contextThreadObject() == TQThread::currentThreadObject()))) { TQApplication::sendEvent( t->obj, &e ); // send event } else { @@ -731,7 +731,7 @@ int TQEventLoop::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() == TQThread::currentThreadObject()))) { + if ((!sn->obj) || (TQThread::currentThreadObject()->threadPostedEventsDisabled()) || (sn->obj && (sn->obj->contextThreadObject() == TQThread::currentThreadObject()))) { TQApplication::sendEvent( sn->obj, &event ); // send event } else { diff --git a/src/kernel/qobject.cpp b/src/kernel/qobject.cpp index d8b2047a..4442023a 100644 --- a/src/kernel/qobject.cpp +++ b/src/kernel/qobject.cpp @@ -2727,7 +2727,7 @@ void TQObject::activate_signal( TQConnectionList *clist, TQUObject *o ) sol->currentSender = this; } if ( c->memberType() == TQSIGNAL_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 TQObject::activate_signal( TQConnectionList *clist, TQUObject *o ) } else { if (object->d->ownThread && !object->d->ownThread->finished()) { +#ifdef QT_DEBUG + tqDebug("TQObject::activate_signal: Emitting cross-thread signal from object %p (member %d receiver %p) (1)\n\r", this, c->member(), object); +#endif // QT_DEBUG TQApplication::postEvent(object, new TQMetaCallEvent(c->member(), this, deepCopyTQUObjectArray(o), TQMetaCallEvent::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 TQObject::activate_signal( TQConnectionList *clist, TQUObject *o ) } else { if (object->d->ownThread && !object->d->ownThread->finished()) { +#ifdef QT_DEBUG + tqDebug("TQObject::activate_signal: Invoking cross-thread method from object %p (member %d receiver %p) (1)\n\r", this, c->member(), object); +#endif // QT_DEBUG TQApplication::postEvent(object, new TQMetaCallEvent(c->member(), this, deepCopyTQUObjectArray(o), TQMetaCallEvent::MetaCallInvoke)); } } @@ -2788,7 +2794,7 @@ void TQObject::activate_signal( TQConnectionList *clist, TQUObject *o ) sol->currentSender = this; } if ( c->memberType() == TQSIGNAL_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 TQObject::activate_signal( TQConnectionList *clist, TQUObject *o ) } else { if (object->d->ownThread && !object->d->ownThread->finished()) { +#ifdef QT_DEBUG + tqDebug("TQObject::activate_signal: Emitting cross-thread signal from object %p (member %d receiver %p) (2)\n\r", this, c->member(), object); +#endif // QT_DEBUG TQApplication::postEvent(object, new TQMetaCallEvent(c->member(), this, deepCopyTQUObjectArray(o), TQMetaCallEvent::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 TQObject::activate_signal( TQConnectionList *clist, TQUObject *o ) } else { if (object->d->ownThread && !object->d->ownThread->finished()) { +#ifdef QT_DEBUG + tqDebug("TQObject::activate_signal: Invoking cross-thread method from object %p (member %d receiver %p) (2)\n\r", this, c->member(), object); +#endif // QT_DEBUG TQApplication::postEvent(object, new TQMetaCallEvent(c->member(), this, deepCopyTQUObjectArray(o), TQMetaCallEvent::MetaCallInvoke)); } } diff --git a/src/kernel/qthread.cpp b/src/kernel/qthread.cpp index 7c882008..86accebb 100644 --- a/src/kernel/qthread.cpp +++ b/src/kernel/qthread.cpp @@ -223,6 +223,29 @@ bool TQThread::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 TQThread::setThreadPostedEventsDisabled(bool disable) +{ + d->disableThreadPostedEvents = disable; +} + +/*! + Returns TRUE if thread posted events are disabled, FALSE if not + */ +bool TQThread::threadPostedEventsDisabled() const +{ + return d->disableThreadPostedEvents; +} + /*! \fn void TQThread::run() diff --git a/src/kernel/qthread_unix.cpp b/src/kernel/qthread_unix.cpp index fb8f4531..6e8c4fdc 100644 --- a/src/kernel/qthread_unix.cpp +++ b/src/kernel/qthread_unix.cpp @@ -105,6 +105,7 @@ void TQThreadInstance::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 *TQThreadInstance::start( void *_arg ) ((TQThreadInstance*)arg[1])->thread_id = pthread_self(); #endif // QT_USE_GLIBMAINLOOP +#ifdef QT_DEBUG + tqDebug("TQThreadInstance::start: Setting thread storage to %p\n\r", (TQThread *) arg[0]); +#endif // QT_DEBUG setCurrentThread( (TQThread *) arg[0] ); pthread_cleanup_push( TQThreadInstance::finish, arg[1] ); @@ -152,6 +156,8 @@ void TQThreadInstance::finish( void * ) return; } + tqDebug("TQThreadInstance::finish: In TQThreadInstance::finish for thread %p\n\r", (TQThread*)d->args[0]); + TQApplication::threadTerminationHandler((TQThread*)d->args[0]); TQMutexLocker locker( d->mutex() ); @@ -510,7 +516,7 @@ bool TQThread::wait( unsigned long time ) \sa CleanupType */ -TQThread::CleanupType TQThread::cleanupType() { +TQThread::CleanupType TQThread::cleanupType() const { return (TQThread::CleanupType)d->cleanupType; } diff --git a/src/tools/qthreadinstance_p.h b/src/tools/qthreadinstance_p.h index 4d5bff99..9fae260e 100644 --- a/src/tools/qthreadinstance_p.h +++ b/src/tools/qthreadinstance_p.h @@ -102,6 +102,7 @@ public: TQEventLoop* eventLoop; int cleanupType; + bool disableThreadPostedEvents : 1; }; #endif // QT_THREAD_SUPPORT diff --git a/tutorial/t15/main.cpp b/tutorial/t15/main.cpp index a5381e60..9277ce17 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); \ - TQObject::connect(&x, SIGNAL(displayMessage(TQString,TQString)), &mainobject, SLOT(emitMessage(TQString,TQString))); \ +#define SET_UP_WORKER(x, y, z) \ + WorkerObject x; \ + x.threadFriendlyName = y; \ + x.moveToThread(&z); \ + TQObject::connect(&x, SIGNAL(displayMessage(TQString,TQString)), &mainobject, SLOT(emitMessage(TQString,TQString))); \ TQTimer::singleShot(0, &x, SLOT(run())); int main( int argc, char **argv )