PDA

View Full Version : QWaitCondition woken by QFuture



ibex
23rd December 2011, 17:11
I am working on some producer/consumer code using QtConcurrent as the producer. The consumer is running in the main GUI thread and I would like it to do something whenever some work is ready. I can use a QWaitCondition and get the producer tasks to call QWaitCondition::wakeOne() when finished but am having trouble exiting the loop when the QFuture reports finished:



Worker worker;
QFuture future=QtConcurrent::map(start, end, worker);

QMutex mutex;
QWaitCondition waitCondition;
mutex.lock();
while (true) {
if (results.ready())
processResults();

if (future.isFinished()) {
mutex.unlock();
break;
else if (waitCondition.wait(&mutex, timeout) {
break;//give up
}
}

Worker::operator() (int i) {
doWork(i);
waitCondition.wakeOne();
}


The trouble is the QFuture may finish between the calls to isFinished() and wait() resulting in a delay of 'timeout'. I would like the QFuture finishing to do a wakeOne() and have tried unsuccessfully using a direct connection to QFutureWatcher::finished(). I think the QFutureWatcher may depend on the event loop and as the consumer is in the main thread, it isn't received.

Would adding something like this be useful Qt enhancement to facilitate this:


QFuture::addFinishedCondition(QWaitCondition wc, bool wakeAll);
QFuture::addResultsReadyCondition(QWaitCondition wc, bool wakeAll);


Is there a solution using existing code?

thanks.

amleto
23rd December 2011, 18:58
seems like you could be using qfuturewatcher and void resultReadyAt ( int index )

Isn't your loop backwards as well? ie the wait should be at the top of the loop.

Also, I'm not sure qwaitcondition and qfuture are meant to go together how you are using. when you call wakeOne, the result for the future is not ready - the function hasnt completed. you are using wakeOne to do exactly what futurewatcher resultReadyAt ( int index ) is meant to do.


There is a solution using existing code - use the signals from futurewatcher. dont use a loop in the main thread that blocks qt from processing events.

ibex
28th December 2011, 19:27
use the signals from futurewatcher. dont use a loop in the main thread that blocks qt from processing events
The reason the consumer is in the main thread is that it is performing rendering.


when you call wakeOne, the result for the future is not ready - the function hasnt completed
The function hasn't completed and the future doesn't know it has finished modifying data yet but I do. It would be better if the future could do the waking as proposed though.

It seems QtConcurrent is a good high level threading module and Qt also provides good lower level code such as QWaitCondition and QMutex, but there is no bridge between the two. I think this may be an unnecessary limitation and providing a mechanism for QFuture to wake QWaitCondition would be a natural extension.

Unfortunately I don't see anyway to change this without modifying Qt private code.

amleto
28th December 2011, 20:10
The reason the consumer is in the main thread is that it is performing rendering.
The consumer can be perfectly happy in the main thread WITHOUT a blocking loop.

It would be better if the future could do the waking as proposed though.
the future would do the waking. if only you would let it.

I don't think any bridge is necessary, and there definitely isn't any limitation imposed here.