Add threading tutorial and fix a couple rare crashes

pull/2/head
Timothy Pearson 12 years ago
parent 78125ea2f0
commit caf80d8824

@ -2767,7 +2767,10 @@ bool QApplication::internalNotify( QObject *receiver, QEvent * e)
if (!handled) {
#if defined(QT_THREAD_SUPPORT)
bool locked = QApplication::qt_mutex->locked();
bool locked = false;
if (QApplication::qt_mutex) {
locked = QApplication::qt_mutex->locked();
}
if (locked) {
QApplication::qt_mutex->unlock();
}
@ -2775,7 +2778,9 @@ bool QApplication::internalNotify( QObject *receiver, QEvent * e)
consumed = receiver->event( e );
#if defined(QT_THREAD_SUPPORT)
if (locked) {
QApplication::qt_mutex->lock();
if (QApplication::qt_mutex) {
QApplication::qt_mutex->lock();
}
}
#endif
}

@ -562,6 +562,8 @@ int QEventLoop::activateTimers()
n_act++;
QTimerEvent e( t->id );
QApplication::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;
}

@ -284,7 +284,8 @@ bool QEventLoop::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 QEventLoop::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

@ -0,0 +1,173 @@
/****************************************************************
**
** Qt threading tutorial
** (c) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net>
**
** This tutorial is released into the Public Domain and
** can therefore be modified and/or used for any purpose
**
****************************************************************/
#include "main.h"
#include <unistd.h>
#include <qtimer.h>
#include <qeventloop.h>
void WorkerObject::run()
{
qDebug( "[%s] thread: %p event loop: %p", threadFriendlyName.ascii(), QThread::currentThreadObject(), QApplication::eventLoop() );
QEventLoop* eventLoop = QApplication::eventLoop();
if (!eventLoop) return;
QTimer *t = new QTimer(this);
connect( t, SIGNAL(timeout()), SLOT(timerHandler()) );
t->start( 1000, FALSE );
for( int count = 0; count < 5; count++ ) {
sleep( 1 );
qDebug( "[%s] Ping!", threadFriendlyName.ascii() );
displayMessage("Hi", "There!");
eventLoop->processEvents(QEventLoop::AllEvents);
}
eventLoop->exit(0);
}
void WorkerObject::timerHandler()
{
qDebug( "[%s] Timer fired!", threadFriendlyName.ascii() );
}
void MainObject::emitMessage(QString str1, QString str2)
{
qDebug( "%s", ("[MainObject] emitMessage: " + str1 + " " + str2).ascii() );
}
void MainObject::buttonClicked()
{
qDebug( "[MainObject] Button clicked!" );
QEventLoop* eventLoop = QApplication::eventLoop();
if (!eventLoop) return;
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))); \
QTimer::singleShot(0, &x, SLOT(run()));
int main( int argc, char **argv )
{
QApplication a( argc, argv );
qDebug( "[MainObject] thread: %p event loop: %p", QThread::currentThreadObject(), QApplication::eventLoop() );
QPushButton hello( "Exit", 0 );
hello.resize( 100, 30 );
MainObject mainobject;
QEventLoopThread workerthread0;
QEventLoopThread workerthread1;
QEventLoopThread workerthread2;
QEventLoopThread workerthread3;
QEventLoopThread workerthread4;
QEventLoopThread workerthread5;
QEventLoopThread workerthread6;
QEventLoopThread workerthread7;
QEventLoopThread workerthread8;
QEventLoopThread workerthread9;
QEventLoopThread workerthread10;
QEventLoopThread workerthread11;
QEventLoopThread workerthread12;
QEventLoopThread workerthread13;
QEventLoopThread workerthread14;
QEventLoopThread workerthread15;
QEventLoopThread workerthread16;
QEventLoopThread workerthread17;
QEventLoopThread workerthread18;
QEventLoopThread 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 );
QObject::connect(&hello, SIGNAL(clicked()), &mainobject, SLOT(buttonClicked()));
hello.show();
a.exec();
hello.hide();
qDebug( "[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();
qDebug( "[MainObject] Finished!" );
}

@ -0,0 +1,45 @@
/****************************************************************
**
** Qt threading tutorial
** (c) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net>
**
** 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 <qapplication.h>
#include <qobject.h>
#include <qpushbutton.h>
#include <qthread.h>
class MainObject;
class WorkerObject : public QObject
{
Q_OBJECT
public slots:
void run();
void timerHandler();
signals:
void displayMessage(QString, QString);
public:
QString threadFriendlyName;
};
class MainObject : public QObject
{
Q_OBJECT
public slots:
void emitMessage(QString, QString);
void buttonClicked();
};
#endif // _MAIN_H_

@ -0,0 +1,5 @@
TEMPLATE = app
CONFIG += qt warn_on release
HEADERS = main.h
SOURCES = main.cpp
TARGET = t15

@ -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

Loading…
Cancel
Save