[Interest] [External]Re: How to get QtConcurrent to do what I want?

Murphy, Sean Sean.Murphy at centauricorp.com
Tue Feb 1 19:35:59 CET 2022


> Depending on your QFuture setup, you could monitor each tile, and when it
> completes, update the min max...

I think from the testing I did yesterday, and this comment from 
https://doc.qt.io/qt-5/qfuturewatcher.html prevents you from knowing WHICH
result is ready if your map function returns void:

"QFutureWatcher<void> is specialized to not contain any of the result fetching 
functions. Any QFuture<T> can be watched by a QFutureWatcher<void> as well. 
This is useful if only status or progress information is needed; not the actual 
result data."

One of my early go arounds yesterday had me connecting the 
QFutureWatcher<void>::resultReadyAt(int index) from the watcher that was monitoring 
the tile::load() call to a slot in my tileManager class. That slot was never called. If I 
used the QFutureWatcher<void>::progressValueChanged(int progressValue) signal 
instead, the slot was called as each tile completed. But the issue there is that you 
only know HOW MANY have completed, not WHICH ONES. 

So from what I could tell, if you want to work with the result of an individual item right 
when it comes in, the function you pass as the map function has to have a non-void return 
type so that you aren't instantiating a QFutureWatcher<void> which doesn't fire those signals, 
but instead instantiate a QFutureWatcher<T> and then you can use the resultReadyAt(int index)

> Passing the manager to each tile, and when the tile is finished update the
> manager with the tiles value.  Then a simple mutex should allow you to not
> collide.  No signals, just a simple function call.

Oh man, my head is already bursting with the QtConcurrent and QFuture stuff, now you want to 
toss QMutex at me too?!?! 😉
 
> When the future watcher says all tiles are done, you will also have the
> min/max computed at that point, so you can kick off phase 2.
> 
> While I love the signal slot for "generic, I don’t know who needs this
> information" type design. Sometimes the cost/overhead of being a qobject
> and sending the signal, especially when it’s a very discrete "signal" and not
> generic in any means, it can be overkill.
> 
> To me, the manager you have doesn’t need to know "is a tile finished", ie a
> generic signal.  But rather what Is the min max of the tile when finished a
> specific signal.  For that level, a simple function works.

From where I'm at right now, I think that can be accomplished by changing my 
loadTile function from:
    void loadTile(tile &t)
    {
        t.load();
    }

    QPair<double,double> loadTile(tile &t)
    {
        t.load();
        return t.getMinMax();
    }

Then change to QtConcurrent::mapped() instead of map() since my future type 
is now QPair<double, double> and then I can connect the 
QFutureWatcher<QPair<double, double>>::resultReadyAt(int index) to a slot that 
updates the global min/max.

Although as I'm reading through everything, this also might the point to use 
QtConcurrent::mappedReduced(). So many options to choose from...

Sean


More information about the Interest mailing list