Spec-Zone.ru › Qt 5.6

Конкурентное фильтрация и фильтрация-сведение

Функции QtConcurrent::filter(), QtConcurrent::filtered() и QtConcurrent::filteredReduced() фильтруют элементы в последовательности, такой как QList или QVector, параллельно. QtConcurrent::filter() изменяет последовательность на месте, QtConcurrent::filtered() возвращает новую последовательность, содержащую отфильтрованный контент, а QtConcurrent::filteredReduced() возвращает единственный результат.

Эти функции являются частью фреймворка Qt Concurrent.

Каждая из вышеперечисленных функций имеет блокирующую разновидность, которая возвращает конечный результат вместо QFuture. Вы используете их так же, как и асинхронные варианты.

QStringList strings = ...;

// each call blocks until the entire operation is finished
QStringList lowerCaseStrings = QtConcurrent::blockingFiltered(strings, allLowerCase);

QtConcurrent::blockingFilter(strings, allLowerCase);

QSet<QString> dictionary = QtConcurrent::blockingFilteredReduced(strings, allLowerCase, addToDictionary);

Обратите внимание, что типы результатов выше не являются объектами QFuture, а реальными типами результатов (в данном случае QStringList и QSet<QString>).

Конкурентное фильтрация

QtConcurrent::filtered() принимает входную последовательность и функцию фильтрации. Затем эта функция фильтрации вызывается для каждого элемента в последовательности, и возвращается новая последовательность, содержащая отфильтрованные значения.

Функция фильтрации должна иметь вид:

bool function(const T &t);

T должен соответствовать типу, хранящемуся в последовательности. Функция возвращает true если элемент должен быть сохранён, false, если он должен быть отброшен.

В этом примере показано, как сохранить строки, которые состоят только из строчных букв, из QStringList:

bool allLowerCase(const QString &string)
{
    return string.lowered() == string;
}

QStringList strings = ...;
QFuture<QString> lowerCaseStrings = QtConcurrent::filtered(strings, allLowerCase);

Результаты фильтра доступны через QFuture. См. документацию QFuture и QFutureWatcher для получения дополнительной информации о том, как использовать QFuture в ваших приложениях.

Если вы хотите изменить последовательность на месте, используйте QtConcurrent::filter():

QStringList strings = ...;
QFuture<void> future = QtConcurrent::filter(strings, allLowerCase);

Поскольку последовательность изменяется на месте, QtConcurrent::filter() не возвращает никаких результатов через QFuture. Однако вы по-прежнему можете использовать QFuture и QFutureWatcher для отслеживания состояния фильтрации.

Конкурентная фильтрация-сведение

QtConcurrent::filteredReduced() аналогичен QtConcurrent::filtered(), но вместо возврата последовательности с отфильтрованными результатами, результаты объединяются в одно значение с помощью функции сведения.

Функция сведения должна иметь вид:

V function(T &result, const U &intermediate)

T — тип конечного результата, U — тип фильтруемых элементов. Обратите внимание, что возвращаемое значение и возвращаемый тип функции сведения не используются.

Вызовите QtConcurrent::filteredReduced() так:

void addToDictionary(QSet<QString> &dictionary, const QString &string)
{
    dictionary.insert(string);
}

QStringList strings = ...;
QFuture<QSet<QString> > dictionary = QtConcurrent::filteredReduced(strings, allLowerCase, addToDictionary);

Функция сведения будет вызываться один раз для каждого результата, сохранённого функцией фильтра, и должна объединить промежуточное значение в переменную результат. QtConcurrent::filteredReduced() гарантирует, что только один поток будет вызывать функцию сведения за раз, поэтому использование мьютекса для блокировки переменной результат не является необходимым. Перечисление QtConcurrent::ReduceOptions предоставляет способ управления порядком выполнения сведения.

Дополнительные функции API

Использование итераторов вместо последовательности

Каждая из вышеперечисленных функций имеет вариант, который принимает диапазон итераторов вместо последовательности. Вы используете их так же, как и варианты с последовательностями:

QStringList strings = ...;
QFuture<QString> lowerCaseStrings = QtConcurrent::filtered(strings.constBegin(), strings.constEnd(), allLowerCase);

// filter in-place only works on non-const iterators
QFuture<void> future = QtConcurrent::filter(strings.begin(), strings.end(), allLowerCase);

QFuture<QSet<QString> > dictionary = QtConcurrent::filteredReduced(strings.constBegin(), strings.constEnd(), allLowerCase, addToDictionary);

Использование методов-членов

QtConcurrent::filter(), QtConcurrent::filtered() и QtConcurrent::filteredReduced() принимают указатели на методы-члены. Тип класса метода-члена должен соответствовать типу, хранящемуся в последовательности:

// keep only images with an alpha channel
QList<QImage> images = ...;
QFuture<void> alphaImages = QtConcurrent::filter(images, &QImage::hasAlphaChannel);

// retrieve gray scale images
QList<QImage> images = ...;
QFuture<QImage> grayscaleImages = QtConcurrent::filtered(images, &QImage::isGrayscale);

// create a set of all printable characters
QList<QChar> characters = ...;
QFuture<QSet<QChar> > set = QtConcurrent::filteredReduced(characters, &QChar::isPrint, &QSet<QChar>::insert);

Обратите внимание, что при использовании QtConcurrent::filteredReduced() вы можете свободно комбинировать использование обычных и методов-членов:

// can mix normal functions and member functions with QtConcurrent::filteredReduced()

// create a dictionary of all lower cased strings
extern bool allLowerCase(const QString &string);
QStringList strings = ...;
QFuture<QSet<int> > averageWordLength = QtConcurrent::filteredReduced(strings, allLowerCase, QSet<QString>::insert);

// create a collage of all gray scale images
extern void addToCollage(QImage &collage, const QImage &grayscaleImage);
QList<QImage> images = ...;
QFuture<QImage> collage = QtConcurrent::filteredReduced(images, &QImage::isGrayscale, addToCollage);

Использование объектов-функций

QtConcurrent::filter(), QtConcurrent::filtered() и QtConcurrent::filteredReduced() принимают объекты-функции, которые могут быть использованы для добавления состояния к вызову функции. Тип результата result_type должен определять тип результата оператора вызова функции:

struct StartsWith
{
    StartsWith(const QString &string)
    : m_string(string) { }

    typedef bool result_type;

    bool operator()(const QString &testString)
    {
        return testString.startsWith(m_string);
    }

    QString m_string;
};

QList<QString> strings = ...;
QFuture<QString> fooString = QtConcurrent::filtered(images, StartsWith(QLatin1String("Foo")));

Использование связанных аргументов функции

Если вы хотите использовать функцию фильтрации, которая принимает более одного аргумента, вы можете использовать std::bind() для преобразования её в функцию, которая принимает один аргумент. Если поддержка C++11 недоступна, boost::bind() или std::tr1::bind() являются подходящими заменителями.

В качестве примера мы используем QString::contains():

bool QString::contains(const QRegExp &regexp) const;

QString::contains() принимает 2 аргумента (включая указатель "this") и не может быть использована напрямую с QtConcurrent::filtered(), потому что QtConcurrent::filtered() ожидает функцию, которая принимает один аргумент. Для использования QString::contains() с QtConcurrent::filtered() мы должны предоставить значение для аргумента regexp:

std::bind(&QString::contains, QRegExp("^\\S+$")); // matches strings without whitespace

Возвращаемое значение от std::bind() — это объект-функция (фуктор) со следующим сигнатуром:

bool contains(const QString &string)

Это соответствует тому, чего ожидает QtConcurrent::filtered(), и полный пример становится:

QStringList strings = ...;
std::bind(static_cast<bool(QString::*)(const QRegExp&)>( &QString::contains ), QRegExp("..." ));

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.6/qtconcurrentfilter.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API