diff --git a/src/kernel/qapplication.cpp b/src/kernel/qapplication.cpp index 5b57bd24..6fade022 100644 --- a/src/kernel/qapplication.cpp +++ b/src/kernel/qapplication.cpp @@ -2767,7 +2767,10 @@ bool TQApplication::internalNotify( TQObject *receiver, TQEvent * e) if (!handled) { #if defined(QT_THREAD_SUPPORT) - bool locked = TQApplication::tqt_mutex->locked(); + bool locked = false; + if (TQApplication::tqt_mutex) { + locked = TQApplication::tqt_mutex->locked(); + } if (locked) { TQApplication::tqt_mutex->unlock(); } @@ -2775,7 +2778,9 @@ bool TQApplication::internalNotify( TQObject *receiver, TQEvent * e) consumed = receiver->event( e ); #if defined(QT_THREAD_SUPPORT) if (locked) { - TQApplication::tqt_mutex->lock(); + if (TQApplication::tqt_mutex) { + TQApplication::tqt_mutex->lock(); + } } #endif } diff --git a/src/kernel/qeventloop_unix.cpp b/src/kernel/qeventloop_unix.cpp index ccdbb4b8..1c391f41 100644 --- a/src/kernel/qeventloop_unix.cpp +++ b/src/kernel/qeventloop_unix.cpp @@ -562,6 +562,8 @@ int TQEventLoop::activateTimers() n_act++; TQTimerEvent e( t->id ); TQApplication::sendEvent( t->obj, &e ); // send event + if ( !timerList ) // sendEvent allows other threads to execute, therefore we must check for list existence when it returns! + return 0; if ( timerList->findRef( begin ) == -1 ) begin = 0; } diff --git a/src/kernel/qeventloop_x11.cpp b/src/kernel/qeventloop_x11.cpp index a2d8590f..a733c115 100644 --- a/src/kernel/qeventloop_x11.cpp +++ b/src/kernel/qeventloop_x11.cpp @@ -284,7 +284,8 @@ bool TQEventLoop::processEvents( ProcessEventsFlags flags ) // unlock the GUI mutex and select. when we return from this function, there is // something for us to do #if defined(QT_THREAD_SUPPORT) - locker.mutex()->unlock(); + if ( locker.mutex() ) locker.mutex()->unlock(); + else return false; #endif int nsel; @@ -298,7 +299,8 @@ bool TQEventLoop::processEvents( ProcessEventsFlags flags ) // relock the GUI mutex before processing any pending events #if defined(QT_THREAD_SUPPORT) - locker.mutex()->lock(); + if ( locker.mutex() ) locker.mutex()->lock(); + else return false; #endif // we are awake, broadcast it diff --git a/tutorial/t15/main.cpp b/tutorial/t15/main.cpp new file mode 100644 index 00000000..b20262bf --- /dev/null +++ b/tutorial/t15/main.cpp @@ -0,0 +1,173 @@ +/**************************************************************** +** +** TQt threading tutorial +** (c) 2012 Timothy Pearson +** +** This tutorial is released into the Public Domain and +** can therefore be modified and/or used for any purpose +** +****************************************************************/ + +#include "main.h" + +#include + +#include +#include + +void WorkerObject::run() +{ + tqDebug( "[%s] thread: %p event loop: %p", threadFriendlyName.ascii(), TQThread::currentThreadObject(), TQApplication::eventLoop() ); + + TQEventLoop* eventLoop = TQApplication::eventLoop(); + if (!eventLoop) return; + + TQTimer *t = new TQTimer(this); + connect( t, SIGNAL(timeout()), SLOT(timerHandler()) ); + t->start( 1000, FALSE ); + + for( int count = 0; count < 5; count++ ) { + sleep( 1 ); + tqDebug( "[%s] Ping!", threadFriendlyName.ascii() ); + displayMessage("Hi", "There!"); + eventLoop->processEvents(TQEventLoop::AllEvents); + } + + eventLoop->exit(0); +} + +void WorkerObject::timerHandler() +{ + tqDebug( "[%s] Timer fired!", threadFriendlyName.ascii() ); +} + +void MainObject::emitMessage(TQString str1, TQString str2) +{ + tqDebug( "%s", ("[MainObject] emitMessage: " + str1 + " " + str2).ascii() ); +} + +void MainObject::buttonClicked() +{ + tqDebug( "[MainObject] Button clicked!" ); + + TQEventLoop* eventLoop = TQApplication::eventLoop(); + if (!eventLoop) return; + 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))); \ + TQTimer::singleShot(0, &x, SLOT(run())); + +int main( int argc, char **argv ) +{ + TQApplication a( argc, argv ); + + tqDebug( "[MainObject] thread: %p event loop: %p", TQThread::currentThreadObject(), TQApplication::eventLoop() ); + + TQPushButton hello( "Exit", 0 ); + hello.resize( 100, 30 ); + + MainObject mainobject; + + TQEventLoopThread workerthread0; + TQEventLoopThread workerthread1; + TQEventLoopThread workerthread2; + TQEventLoopThread workerthread3; + TQEventLoopThread workerthread4; + TQEventLoopThread workerthread5; + TQEventLoopThread workerthread6; + TQEventLoopThread workerthread7; + TQEventLoopThread workerthread8; + TQEventLoopThread workerthread9; + + TQEventLoopThread workerthread10; + TQEventLoopThread workerthread11; + TQEventLoopThread workerthread12; + TQEventLoopThread workerthread13; + TQEventLoopThread workerthread14; + TQEventLoopThread workerthread15; + TQEventLoopThread workerthread16; + TQEventLoopThread workerthread17; + TQEventLoopThread workerthread18; + TQEventLoopThread workerthread19; + + SET_UP_WORKER(workerobject0, "WorkerObject0", workerthread0) + SET_UP_WORKER(workerobject1, "WorkerObject1", workerthread1) + SET_UP_WORKER(workerobject2, "WorkerObject2", workerthread2) + SET_UP_WORKER(workerobject3, "WorkerObject3", workerthread3) + SET_UP_WORKER(workerobject4, "WorkerObject4", workerthread4) + SET_UP_WORKER(workerobject5, "WorkerObject5", workerthread5) + SET_UP_WORKER(workerobject6, "WorkerObject6", workerthread6) + SET_UP_WORKER(workerobject7, "WorkerObject7", workerthread7) + SET_UP_WORKER(workerobject8, "WorkerObject8", workerthread8) + SET_UP_WORKER(workerobject9, "WorkerObject9", workerthread9) + + SET_UP_WORKER(workerobject10, "WorkerObjec10", workerthread10) + SET_UP_WORKER(workerobject11, "WorkerObjec11", workerthread11) + SET_UP_WORKER(workerobject12, "WorkerObjec12", workerthread12) + SET_UP_WORKER(workerobject13, "WorkerObjec13", workerthread13) + SET_UP_WORKER(workerobject14, "WorkerObjec14", workerthread14) + SET_UP_WORKER(workerobject15, "WorkerObjec15", workerthread15) + SET_UP_WORKER(workerobject16, "WorkerObjec16", workerthread16) + SET_UP_WORKER(workerobject17, "WorkerObjec17", workerthread17) + SET_UP_WORKER(workerobject18, "WorkerObjec18", workerthread18) + SET_UP_WORKER(workerobject19, "WorkerObjec19", workerthread19) + + workerthread0.start(); + workerthread1.start(); + workerthread2.start(); + workerthread3.start(); + workerthread4.start(); + workerthread5.start(); + workerthread6.start(); + workerthread7.start(); + workerthread8.start(); + workerthread9.start(); + + workerthread10.start(); + workerthread11.start(); + workerthread12.start(); + workerthread13.start(); + workerthread14.start(); + workerthread15.start(); + workerthread16.start(); + workerthread17.start(); + workerthread18.start(); + workerthread19.start(); + + a.setMainWidget( &hello ); + TQObject::connect(&hello, SIGNAL(clicked()), &mainobject, SLOT(buttonClicked())); + hello.show(); + a.exec(); + hello.hide(); + + tqDebug( "[MainObject] Waiting for thread completion..." ); + + workerthread0.wait(); + workerthread1.wait(); + workerthread2.wait(); + workerthread3.wait(); + workerthread4.wait(); + workerthread5.wait(); + workerthread6.wait(); + workerthread7.wait(); + workerthread8.wait(); + workerthread9.wait(); + + workerthread10.wait(); + workerthread11.wait(); + workerthread12.wait(); + workerthread13.wait(); + workerthread14.wait(); + workerthread15.wait(); + workerthread16.wait(); + workerthread17.wait(); + workerthread18.wait(); + workerthread19.wait(); + + tqDebug( "[MainObject] Finished!" ); +} diff --git a/tutorial/t15/main.h b/tutorial/t15/main.h new file mode 100644 index 00000000..6cb8ee8e --- /dev/null +++ b/tutorial/t15/main.h @@ -0,0 +1,45 @@ +/**************************************************************** +** +** TQt threading tutorial +** (c) 2012 Timothy Pearson +** +** This tutorial is released into the Public Domain and +** can therefore be modified and/or used for any purpose +** +****************************************************************/ + +#ifndef _MAIN_H_ +#define _MAIN_H_ + +#include +#include +#include +#include + +class MainObject; + +class WorkerObject : public TQObject +{ + TQ_OBJECT + + public slots: + void run(); + void timerHandler(); + + signals: + void displayMessage(TQString, TQString); + + public: + TQString threadFriendlyName; +}; + +class MainObject : public TQObject +{ + TQ_OBJECT + + public slots: + void emitMessage(TQString, TQString); + void buttonClicked(); +}; + +#endif // _MAIN_H_ diff --git a/tutorial/t15/t15.pro b/tutorial/t15/t15.pro new file mode 100644 index 00000000..ff0f08d9 --- /dev/null +++ b/tutorial/t15/t15.pro @@ -0,0 +1,5 @@ +TEMPLATE = app +CONFIG += qt warn_on release +HEADERS = main.h +SOURCES = main.cpp +TARGET = t15 diff --git a/tutorial/tutorial.pro b/tutorial/tutorial.pro index 32b31d7b..90e37f78 100644 --- a/tutorial/tutorial.pro +++ b/tutorial/tutorial.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS = t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14 +SUBDIRS = t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14 t15