summaryrefslogtreecommitdiffstats
path: root/examples/qtconcurrent/primecounter/primecounter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/qtconcurrent/primecounter/primecounter.cpp')
-rw-r--r--examples/qtconcurrent/primecounter/primecounter.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/examples/qtconcurrent/primecounter/primecounter.cpp b/examples/qtconcurrent/primecounter/primecounter.cpp
new file mode 100644
index 0000000000..01bde5d87f
--- /dev/null
+++ b/examples/qtconcurrent/primecounter/primecounter.cpp
@@ -0,0 +1,139 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "primecounter.h"
+#include "ui_primecounter.h"
+
+PrimeCounter::PrimeCounter(QWidget *parent)
+ : QDialog(parent), stepSize(100000), ui(setupUi())
+{
+ // Control the concurrent operation with the QFutureWatcher
+ //! [1]
+ connect(ui->pushButton, &QPushButton::clicked,
+ this, [this] { start(); });
+ connect(&watcher, &QFutureWatcher<Element>::finished,
+ this, [this] { finish(); });
+ connect(&watcher, &QFutureWatcher<Element>::progressRangeChanged,
+ ui->progressBar, &QProgressBar::setRange);
+ connect(&watcher, &QFutureWatcher<Element>::progressValueChanged,
+ ui->progressBar, &QProgressBar::setValue);
+ //! [1]
+}
+
+PrimeCounter::~PrimeCounter()
+{
+ watcher.cancel();
+ delete ui;
+}
+
+//! [3]
+bool PrimeCounter::filterFunction(const Element &element)
+{
+ // Filter for primes
+ if (element <= 1)
+ return false;
+ for (Element i = 2; i*i <= element; ++i) {
+ if (element % i == 0)
+ return false;
+ }
+ return true;
+}
+//! [3]
+
+//! [4]
+void PrimeCounter::reduceFunction(Element &out, const Element &value)
+{
+ // Count the amount of primes.
+ Q_UNUSED(value);
+ ++out;
+}
+//! [4]
+
+//! [2]
+void PrimeCounter::start()
+{
+ if (ui->pushButton->isChecked()) {
+ ui->comboBox->setEnabled(false);
+ ui->pushButton->setText(tr("Cancel"));
+ ui->labelResult->setText(tr("Calculating ..."));
+ ui->labelFilter->setText(tr("Selected Reduce Option: %1").arg(ui->comboBox->currentText()));
+ fillElementList(ui->horizontalSlider->value() * stepSize);
+
+ timer.start();
+ watcher.setFuture(
+ QtConcurrent::filteredReduced(
+ &pool,
+ elementList,
+ filterFunction,
+ reduceFunction,
+ currentReduceOpt | QtConcurrent::SequentialReduce));
+//! [2]
+ } else {
+ watcher.cancel();
+ ui->progressBar->setValue(0);
+ ui->comboBox->setEnabled(true);
+ ui->labelResult->setText(tr(""));
+ ui->pushButton->setText(tr("Start"));
+ ui->labelFilter->setText(tr("Operation Canceled"));
+ }
+}
+
+void PrimeCounter::finish()
+{
+ // The finished signal from the QFutureWatcher is also emitted when cancelling.
+ if (watcher.isCanceled())
+ return;
+
+ auto elapsedTime = timer.elapsed();
+ ui->progressBar->setValue(0);
+ ui->comboBox->setEnabled(true);
+ ui->pushButton->setChecked(false);
+ ui->pushButton->setText(tr("Start"));
+ ui->labelFilter->setText(
+ tr("Filter '%1' took %2 ms to calculate").arg(ui->comboBox->currentText())
+ .arg(elapsedTime));
+ ui->labelResult->setText(
+ tr("Found %1 primes in the range of elements").arg(watcher.result()));
+}
+
+void PrimeCounter::fillElementList(unsigned int count)
+{
+ // Fill elementList with values from [1, count] when starting the calculations.
+ auto prevSize = elementList.size();
+ if (prevSize == count)
+ return; // Nothing to do here.
+
+ auto startVal = elementList.empty() ? 1 : elementList.back() + 1;
+ elementList.resize(count);
+ if (elementList.begin() + prevSize < elementList.end())
+ std::iota(elementList.begin() + prevSize, elementList.end(), startVal);
+}
+
+Ui::PrimeCounter* PrimeCounter::setupUi()
+{
+ Ui::PrimeCounter *setupUI = new Ui::PrimeCounter;
+ setupUI->setupUi(this);
+ setModal(true);
+
+ // Set up the slider
+ connect(setupUI->horizontalSlider, &QSlider::valueChanged,
+ this, [setupUI, this] (const int &pos) {
+ setupUI->labelResult->setText("");
+ setupUI->labelSize->setText(tr("Elements in list: %1").arg(pos * stepSize));
+ });
+ setupUI->horizontalSlider->setValue(30);
+
+ // Set up the combo box
+ setupUI->comboBox->insertItem(0, tr("Unordered Reduce"), QtConcurrent::UnorderedReduce);
+ setupUI->comboBox->insertItem(1, tr("Ordered Reduce"), QtConcurrent::OrderedReduce);
+
+ auto comboBoxChange = [this, setupUI](int pos) {
+ currentReduceOpt = setupUI->comboBox->itemData(pos).value<QtConcurrent::ReduceOptions>();
+ setupUI->labelFilter->setText(tr("Selected Reduce Option: %1")
+ .arg(setupUI->comboBox->currentText()));
+ };
+ comboBoxChange(setupUI->comboBox->currentIndex());
+ connect(setupUI->comboBox, &QComboBox::currentIndexChanged, this, comboBoxChange);
+
+ return setupUI;
+}