I was running into problems in release mode in some threaded code and narrowed down the problem to the following lines.
QFutureWatcher<Result> watcher;
QList<Job> jobs;
...
if(jobs.isEmpty() || watcher.isStarted() && !watcher.isFinished())
return;
watcher.setFuture(QtConcurrent::run(..., jobs.takeFirst()));
QFutureWatcher<Result> watcher;
QList<Job> jobs;
...
if(jobs.isEmpty() || watcher.isStarted() && !watcher.isFinished())
return;
watcher.setFuture(QtConcurrent::run(..., jobs.takeFirst()));
To copy to clipboard, switch view to plain text mode
The problem is that the first time this code is run(watcher is only default constructed) the expression "watcher.isStarted() && !watcher.isFinished()" evaluates to true, but only in release mode.
After sifting through some code I found out that the trolls decided that a default constructed QFuture is supposed to have the states Started | Finished | Canceled, which might be a bit counter-intuitive, but is fine by me.
The problem is that the following program:
#include <QDebug>
#include <QFutureWatcher>
int main()
{
QFutureWatcher<int> watcher;
qDebug()<<"isStarted()"<<watcher.isStarted();
qDebug()<<"isFinished()"<<watcher.isFinished();
qDebug()<<"isCanceled()"<<watcher.isCanceled();
return 1;
}
#include <QDebug>
#include <QFutureWatcher>
int main()
{
QFutureWatcher<int> watcher;
qDebug()<<"isStarted()"<<watcher.isStarted();
qDebug()<<"isFinished()"<<watcher.isFinished();
qDebug()<<"isCanceled()"<<watcher.isCanceled();
return 1;
}
To copy to clipboard, switch view to plain text mode
gives the following output in release mode:
isStarted() true
isFinished() false
isCanceled() true
isStarted() true
isFinished() false
isCanceled() true
To copy to clipboard, switch view to plain text mode
whereas if you exchange QFutureWatcher with QFuture it gives the expected output.
I have tried it with MSVC 2008 and Qt 4.6.2 and would like to here if anyone can confirm this, or even better explain how it can happen.
Bookmarks