Briefly
Qtconcurrent::map (), qtconcurrent::mapped () and qtconcurrent::mappedreduced () function to run calculations in parallel on items in a sequence (for example: Qlist or Qvector). Qtconcurrent::map () Modifies a sequence directly, qtconcurrent::mapped () returns a new sequence containing the modified content, and qtconcurrent::mappedreduced () returns a separate result.
These functions are part of the concurrent framework of QT.
Each of these functions has a blocking variable that returns the final result instead of a qfuture. Use them in the same way as asynchronous variables.
...;// 每一个都调用blocks,直到整个操作完成QList<QImage> future = QtConcurrent::blockingMapped(images, scaled);QtConcurrent::blockingMap(images, scale);QImage collage = QtConcurrent::blockingMappedReduced(images, scaled, addToCollage);
Note: The result type above is not a Qfuture object, but the actual result type (in this case, QList<QImage>
and Qimage).
- Briefly
- Concurrent Map
- Concurrent Map-reduce
- Additional API Features
- Using iterators instead of sequences
- Blocking variable
- Using member functions
- Working with Function objects
- Using binding function parameters
- More references
Concurrent Map
Qtconcurrent::mapped () accepts an input sequence and a map function, which is called by each item in the sequence and returns a new sequence containing the return value of the map function.
The map function must be in the following form:
function(const T &t);
T and u can be any type (they can even be of the same type), but T must match the type stored in the sequence, and the function returns the content that was modified or mapped.
This example shows how to apply the scale function for all the item in a sequence:
QImage scaled(const QImage &image){ return image.scaled(100100...;QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scaled);
The results of map are available through qfuture. Check out the documentation for Qfuture and Qfuturewatcher for more information on how to use qfutured in your application.
If you want to modify a sequence directly, use Qtconcurrent::map (). The map function must be in the following form:
function(T &t);
Note: The return value and return type of the map function are not used.
Use Qtconcurrent::map () and use qtconcurrent::mapped () similar to:
void scale(QImage &image){ image = image.scaled(100100...;QFuture<void> future = QtConcurrent::map(images, scale);
Because the sequence is modified directly, Qtconcurrent::map () does not return any results through qfuture. However, you can still use qfuture and qfuturewatcher to monitor the status of the map.
Concurrent Map-reduce
Qtconcurrent::mappedreduced () is similar to qtconcurrent::mapped (), but returns a new result sequence that, through a reduce function, is combined into a single value.
The reduce function must be in the following form:
function(T &result, const U &intermediate)
T is the type of the final result, and U is the return type of the map function. Note: The return value, return type of the reduce function is not used.
Call qtconcurrent::mappedreduced () as follows:
void addToCollage(QImage &collage, const QImage &thumbnail){ QPainter p(&collage); static QPoint offset = QPoint(00); p.drawImage(offset, thumbnail); ......;QFuture<QImage> collage = QtConcurrent::mappedReduced(images, scaled, addToCollage);
The reduce function is called once for each result returned by the map function, and the intermediate to the result variable should be merged. Qtconcurrent::mappedreduced () guarantees that only one thread will call reduce at a time, so it is not necessary to lock the result variable with a mutex. The Qtconcurrent::reduceoptions enumeration provides a way to control the order in which reduction is completed. If Qtconcurrent::unorderedreduce (default) is used, the order is indeterminate, while qtconcurrent::orderedreduce ensures that the reduction is completed in the order of the original sequence.
Additional API features use iterators instead of sequences
Each of these functions has a variable that requires an iterator range instead of a sequence. Use them in the same way as the sequence variables.
...in-place only works on non-const iteratorsQFuture<void> future = QtConcurrent::map(images.begin(), images.end(), scale);QFuture<QImage> collage = QtConcurrent::mappedReduced(images.constBegin(), images.constEnd(), scaled, addToCollage);
Blocking variable
Each of these functions can have a blocking variable that returns the final result instead of a qfuture. Use them in the same way as asynchronous variables.
...;// each call blocks until the entire operation is finishedQList<QImage> future = QtConcurrent::blockingMapped(images, scaled);QtConcurrent::blockingMap(images, scale);QImage collage = QtConcurrent::blockingMappedReduced(images, scaled, addToCollage);
Note: The result type above is not a Qfuture object, but the actual result type (in this case, QList<QImage>
and Qimage).
Using member functions
Qtconcurrent::map (), qtconcurrent::mapped (), and qtconcurrent::mappedreduced () accept pointers to member functions, and the member function class types must match the types stored in the sequence:
in......in...;QFuture<QSet<int> > wordLengths = QtConcurrent::mappedReduced(string, &QString::length, &QSet<int>::insert);
Note: When using qtconcurrent::mappedreduced (), you can freely combine the use of normal functions and member functions:
...in...;QFuture<QSet<int> > totalColorDistribution = QtConcurrent::mappedReduced(images, colorDistribution, QSet<int>::insert);
Working with Function objects
Qtconcurrent::map (), qtconcurrent::mapped (), and qtconcurrent::mappedreduced () Accept function objects, which can be used to add state function calls. The result_type typedef must define the result type of the function invocation operation:
struct Scaled{ Scaled(int size) : m_size(size) { } typedef QImage result_type; QImage operator()(const QImage &image) { return image.scaled(m_size, m_size); } ...;QFuture<QImage> thumbnails = QtConcurrent::mapped(images, Scaled(100));
Using binding function parameters
If you want to use a map function, it accepts multiple arguments and can use Std::bind () to convert it to a function that takes a parameter. If C + + 11 support is not available, boost::bind () or Std::tr1::bind () is the appropriate alternative.
For example, we will use Qimage::scaledtowidth ():
QImage QImage::scaledToWidth(intconst;
The Scaledtowidth receives three parameters (including the "This" pointer) and cannot be used directly with qtconcurrent::mapped () because qtconcurrent::mapped () requires a function that accepts a parameter. In order to use Qimage::scaledtowidth () with qtconcurrent::mapped (), we must provide a value for the width and transformation mode:
std::bind(&QImage::scaledToWidthQt::SmoothTransformation)
The return value of Std::bind () is a function object with the following signature (functor):
QImage scaledToWith(const QImage &image)
This is in line with qtconcurrent::mapped () expectations, and the complete example becomes:
...100 Qt::SmoothTransformation));
More references
- Concurrent Map and Map-reduce-helper
QT Concurrent Map and Map-reduce