Greetings!
I'm having a problem with my QThread classes. I based them on the Qt Example Mandlebrot (I'm also doing an long rendering process). I extracted the core mutex and waitCondition syncronization that was in the renderThread into it's own class (which I call InfiniteThread) and then I sub-class this to specialize what task that thread will perform.
Problem is, whenever an instance of InfiniteThread is destroyed and the destructor gets called I get a SIGABRT and the following console output:
pure virtual method called
terminate called without an active exception
The program has unexpectedly finished.
Here's the top of the stack at the time:
0 __semwait_signal 0 0x00007fff87ecdeb6
1 _pthread_cond_wait 0 0x00007fff87ed1cd1
3 QThread::wait 0 0x00000001010a419e
4 InfiniteThread::~InfiniteThread infinitethread.cpp 17 0x000000010001022c
5 EMSampleThread::~EMSampleThread emsamplethread.cpp 18 0x000000010000fbfd
6 RFViewer::~RFViewer rfviewer.cpp 50 0x0000000100008a8f
7 main main.cpp 10 0x000000010000602a
0 __semwait_signal 0 0x00007fff87ecdeb6
1 _pthread_cond_wait 0 0x00007fff87ed1cd1
2 QWaitCondition::wait 0 0x000000010103bfa0
3 QThread::wait 0 0x00000001010a419e
4 InfiniteThread::~InfiniteThread infinitethread.cpp 17 0x000000010001022c
5 EMSampleThread::~EMSampleThread emsamplethread.cpp 18 0x000000010000fbfd
6 RFViewer::~RFViewer rfviewer.cpp 50 0x0000000100008a8f
7 main main.cpp 10 0x000000010000602a
To copy to clipboard, switch view to plain text mode
So the SIGABRT seems to be coming from QThread::wait(), which is called in ~InfiniteThread(). Code for InfiniteThread is included below. Note that InfiniteThread::centralTask() is a pure-virtual member that is re-implemented to specialize the thread for a specific task.
Like I mentioned before, InfiniteThread is based entirely on renderthread.cpp in the Mandlebrot example and it does not have this problem. Any help is much appreciated. I'm new to threading but I am pretty comfortable with Qt.
Thanks!
Seth
InfiniteThread.h:
#ifndef INFINITETHREAD_H
#define INFINITETHREAD_H
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
class InfiniteThread
: public QThread{
Q_OBJECT
public:
explicit InfiniteThread
(QObject *parent
= 0);
~InfiniteThread();
signals:
void reportProgress
(int pProg,
QString message
);
void taskDone(bool pSuccess);
protected:
void startTask();
void run();
// Override this in the child class
virtual bool centralTask() = 0;
bool restart;
bool abort;
};
#endif // INFINITETHREAD_H
#ifndef INFINITETHREAD_H
#define INFINITETHREAD_H
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
class InfiniteThread : public QThread
{
Q_OBJECT
public:
explicit InfiniteThread(QObject *parent = 0);
~InfiniteThread();
signals:
void reportProgress(int pProg, QString message);
void taskDone(bool pSuccess);
protected:
void startTask();
void run();
// Override this in the child class
virtual bool centralTask() = 0;
QMutex mutex;
QWaitCondition condition;
bool restart;
bool abort;
};
#endif // INFINITETHREAD_H
To copy to clipboard, switch view to plain text mode
InfiniteThread.cpp:
#include "infinitethread.h"
InfiniteThread
::InfiniteThread(QObject *parent
) :{
restart = false;
abort = false;
}
InfiniteThread::~InfiniteThread()
{
mutex.lock();
abort = true;
condition.wakeOne();
mutex.unlock();
wait();
}
void InfiniteThread::startTask()
{
if (!isRunning()) {
start(LowPriority);
} else {
restart = true;
condition.wakeOne();
}
}
void InfiniteThread::run()
{
forever {
// Perform central task
bool result = centralTask();
if(!restart) emit taskDone(result);
// Abort thread if requested
if(abort) return;
// Restart when new central task is given
mutex.lock();
if(!restart) condition.wait(&mutex);
restart = false;
mutex.unlock();
}
}
#include "infinitethread.h"
InfiniteThread::InfiniteThread(QObject *parent) :
QThread(parent)
{
restart = false;
abort = false;
}
InfiniteThread::~InfiniteThread()
{
mutex.lock();
abort = true;
condition.wakeOne();
mutex.unlock();
wait();
}
void InfiniteThread::startTask()
{
QMutexLocker locker(&mutex);
if (!isRunning()) {
start(LowPriority);
} else {
restart = true;
condition.wakeOne();
}
}
void InfiniteThread::run()
{
forever {
// Perform central task
bool result = centralTask();
if(!restart) emit taskDone(result);
// Abort thread if requested
if(abort) return;
// Restart when new central task is given
mutex.lock();
if(!restart) condition.wait(&mutex);
restart = false;
mutex.unlock();
}
}
To copy to clipboard, switch view to plain text mode
Bookmarks