Concurrent Map and Map-Reduce

The QtConcurrent::map(), QtConcurrent::mapped() and QtConcurrent::mappedReduced() functions run computations in parallel on the items in a sequence such as a QList or a QVector. QtConcurrent::map() modifies a sequence in-place, QtConcurrent::mapped() returns a new sequence containing the modified content, and QtConcurrent::mappedReduced() returns a single result.

Note that the result types above are not QFuture objects, but real result types (in this case, QList<QImage> and QImage).

Concurrent Map

QtConcurrent::mapped() takes an input sequence and a map function. This map function is then called for each item in the sequence, and a new sequence containing the return values from the map function is returned.

The map function must be of the form:

U function(const T &t);

T and U can be any type (and they can even be the same type), but T must match the type stored in the sequence. The function returns the modified or mapped content.

This example shows how to apply a scale function to all the items in a sequence:

The reduce function will be called once for each result returned by the map function, and should merge the intermediate into the result variable. QtConcurrent::mappedReduced() guarantees that only one thread will call reduce at a time, so using a mutex to lock the result variable is not necessary. The QtConcurrent::ReduceOptions enum provides a way to control the order in which the reduction is done. If QtConcurrent::UnorderedReduce is used (the default), the order is undefined, while QtConcurrent::OrderedReduce ensures that the reduction is done in the order of the original sequence.

Additional API Features

Using Iterators instead of Sequence

Each of the above functions has a variant that takes an iterator range instead of a sequence. You use them in the same way as the sequence variants:

Note that when using QtConcurrent::mappedReduced(), you can mix the use of normal and member functions freely:

// can mix normal functions and member functions with QtConcurrent::mappedReduced()// compute the average length of a list of stringsexternvoid computeAverage(int&average,int length);
QStringList strings =...;
QFuture<int> averageWordLength =QtConcurrent::mappedReduced(strings,&QString::length, computeAverage);
// create a set of the color distribution of all images in a listexternint colorDistribution(constQImage&string);
QList<QImage> images =...;
QFuture<QSet<int>> totalColorDistribution =QtConcurrent::mappedReduced(images, colorDistribution,QSet<int>::insert);

Using Function Objects

QtConcurrent::map(), QtConcurrent::mapped(), and QtConcurrent::mappedReduced() accept function objects, which can be used to add state to a function call. The result_type typedef must define the result type of the function call operator:

scaledToWidth takes three arguments (including the "this" pointer) and can't be used with QtConcurrent::mapped() directly, because QtConcurrent::mapped() expects a function that takes one argument. To use QImage::scaledToWidth() with QtConcurrent::mapped() we have to provide a value for the width and the transformation mode: