1-goldbach/{v4.0 → v4.1}/GoldbachModel.cpp RENAMED
@@ -1,114 +1,134 @@
1
  #include "GoldbachModel.h"
2
  #include "GoldbachWorker.h"
3
 
 
 
4
  GoldbachModel::GoldbachModel(QObject *parent)
5
  : QAbstractListModel(parent)
6
  {
7
  }
8
 
9
  int GoldbachModel::rowCount(const QModelIndex &parent) const
10
  {
11
  Q_UNUSED(parent);
12
  return this->fetchedRowCount;
13
  }
14
 
15
  QVariant GoldbachModel::data(const QModelIndex &index, int role) const
16
  {
17
  if (!index.isValid())
18
  return QVariant();
19
 
20
  if (index.row() >= this->countResults() || index.row() < 0)
21
  return QVariant();
22
 
23
  if (role == Qt::DisplayRole)
24
- return findValue( index.row() );
25
 
26
  return QVariant();
27
  }
28
 
29
  const QString &GoldbachModel::findValue(int index) const
30
  {
31
  int row = 0;
32
  while ( index >= this->results[row].count() )
33
  index -= this->results[row++].count();
34
 
35
  return this->results[row][index];
36
  }
37
 
38
  int GoldbachModel::countResults() const
39
  {
40
  int resultCount = 0;
41
  for ( auto vector : this->results )
42
  resultCount += vector.count();
43
 
44
  return resultCount;
45
  }
46
 
47
  void GoldbachModel::calculate(long long number)
48
  {
49
  this->beginResetModel();
50
 
51
  for ( GoldbachWorker* worker : this->workers )
52
  worker->deleteLater();
53
  this->workers.clear();
54
 
55
  int workerCount = qMin( QThread::idealThreadCount(), static_cast<int>(number - 2));
56
 
 
 
 
 
 
57
  this->results.clear();
58
  this->results.resize( workerCount );
59
 
 
 
60
  for ( int current = 0; current < workerCount; ++current )
61
  {
62
  //this->worker = new GoldbachWorker{number, this->results, this};
63
  GoldbachWorker* worker = new GoldbachWorker{number, current, workerCount, this->results[current], this};
64
  this->workers.append( worker );
65
 
66
  this->connect( worker, &GoldbachWorker::progressUpdated, this, &GoldbachModel::updateProgress );
67
  this->connect( worker, &GoldbachWorker::calculationDone, this, &GoldbachModel::workerDone );
68
 
69
  worker->start();
70
  }
71
 
72
  this->endResetModel();
73
  }
74
 
75
  void GoldbachModel::stop()
76
  {
77
  Q_ASSERT(this->workers.count() > 0);
78
  for ( GoldbachWorker* worker : this->workers )
79
  worker->requestInterruption();
80
  }
81
 
82
  bool GoldbachModel::canFetchMore(const QModelIndex &parent) const
83
  {
84
  Q_UNUSED(parent);
85
  return this->fetchedRowCount < this->countResults();
86
  }
87
 
88
  void GoldbachModel::fetchMore(const QModelIndex &parent)
89
  {
90
  Q_UNUSED(parent);
91
 
92
  int remainder = this->countResults() - this->fetchedRowCount;
93
  int itemsToFetch = qMin(100, remainder);
94
 
95
  if (itemsToFetch <= 0)
96
  return;
97
 
98
  beginInsertRows(QModelIndex(), this->fetchedRowCount, this->fetchedRowCount + itemsToFetch - 1);
99
  this->fetchedRowCount += itemsToFetch;
100
  endInsertRows();
101
  }
102
 
103
  void GoldbachModel::workerDone(long long sumCount)
104
  {
 
 
105
  emit this->calculationDone(sumCount);
106
  }
107
 
108
- void GoldbachModel::updateProgress(int percent)
109
  {
 
 
 
 
 
 
 
 
110
  emit this->progressUpdated(percent);
 
111
 
112
  if ( this->fetchedRowCount <= 0 )
113
  this->fetchMore(QModelIndex());
114
  }
1
  #include "GoldbachModel.h"
2
  #include "GoldbachWorker.h"
3
 
4
+ #include <algorithm>
5
+
6
  GoldbachModel::GoldbachModel(QObject *parent)
7
  : QAbstractListModel(parent)
8
  {
9
  }
10
 
11
  int GoldbachModel::rowCount(const QModelIndex &parent) const
12
  {
13
  Q_UNUSED(parent);
14
  return this->fetchedRowCount;
15
  }
16
 
17
  QVariant GoldbachModel::data(const QModelIndex &index, int role) const
18
  {
19
  if (!index.isValid())
20
  return QVariant();
21
 
22
  if (index.row() >= this->countResults() || index.row() < 0)
23
  return QVariant();
24
 
25
  if (role == Qt::DisplayRole)
26
+ return this->findValue( index.row() );
27
 
28
  return QVariant();
29
  }
30
 
31
  const QString &GoldbachModel::findValue(int index) const
32
  {
33
  int row = 0;
34
  while ( index >= this->results[row].count() )
35
  index -= this->results[row++].count();
36
 
37
  return this->results[row][index];
38
  }
39
 
40
  int GoldbachModel::countResults() const
41
  {
42
  int resultCount = 0;
43
  for ( auto vector : this->results )
44
  resultCount += vector.count();
45
 
46
  return resultCount;
47
  }
48
 
49
  void GoldbachModel::calculate(long long number)
50
  {
51
  this->beginResetModel();
52
 
53
  for ( GoldbachWorker* worker : this->workers )
54
  worker->deleteLater();
55
  this->workers.clear();
56
 
57
  int workerCount = qMin( QThread::idealThreadCount(), static_cast<int>(number - 2));
58
 
59
+ this->progressPercents.clear();
60
+ this->progressPercents.resize(workerCount);
61
+
62
+ this->finishedWorkerCount = 0;
63
+
64
  this->results.clear();
65
  this->results.resize( workerCount );
66
 
67
+ this->workers.reserve(workerCount);
68
+
69
  for ( int current = 0; current < workerCount; ++current )
70
  {
71
  //this->worker = new GoldbachWorker{number, this->results, this};
72
  GoldbachWorker* worker = new GoldbachWorker{number, current, workerCount, this->results[current], this};
73
  this->workers.append( worker );
74
 
75
  this->connect( worker, &GoldbachWorker::progressUpdated, this, &GoldbachModel::updateProgress );
76
  this->connect( worker, &GoldbachWorker::calculationDone, this, &GoldbachModel::workerDone );
77
 
78
  worker->start();
79
  }
80
 
81
  this->endResetModel();
82
  }
83
 
84
  void GoldbachModel::stop()
85
  {
86
  Q_ASSERT(this->workers.count() > 0);
87
  for ( GoldbachWorker* worker : this->workers )
88
  worker->requestInterruption();
89
  }
90
 
91
  bool GoldbachModel::canFetchMore(const QModelIndex &parent) const
92
  {
93
  Q_UNUSED(parent);
94
  return this->fetchedRowCount < this->countResults();
95
  }
96
 
97
  void GoldbachModel::fetchMore(const QModelIndex &parent)
98
  {
99
  Q_UNUSED(parent);
100
 
101
  int remainder = this->countResults() - this->fetchedRowCount;
102
  int itemsToFetch = qMin(100, remainder);
103
 
104
  if (itemsToFetch <= 0)
105
  return;
106
 
107
  beginInsertRows(QModelIndex(), this->fetchedRowCount, this->fetchedRowCount + itemsToFetch - 1);
108
  this->fetchedRowCount += itemsToFetch;
109
  endInsertRows();
110
  }
111
 
112
  void GoldbachModel::workerDone(long long sumCount)
113
  {
114
+ Q_ASSERT( this->finishedWorkerCount < this->workers.count() );
115
+ if ( ++this->finishedWorkerCount == this->workers.count() )
116
  emit this->calculationDone(sumCount);
117
  }
118
 
119
+ void GoldbachModel::updateProgress(int workerId, int percent)
120
  {
121
+ Q_ASSERT(workerId >= 0 && workerId < this->progressPercents.count());
122
+ this->progressPercents[workerId] = percent;
123
+
124
+ int minProgressPercent = * std::min_element( this->progressPercents.constBegin(), this->progressPercents.constEnd() );
125
+
126
+ if ( this->overallProgressPercent != minProgressPercent )
127
+ {
128
+ this->overallProgressPercent = minProgressPercent;
129
  emit this->progressUpdated(percent);
130
+ }
131
 
132
  if ( this->fetchedRowCount <= 0 )
133
  this->fetchMore(QModelIndex());
134
  }