Isis 3 Programmer Reference
ConcurrentControlNetReader.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "ConcurrentControlNetReader.h"
10
11#include <algorithm>
12#include <iostream>
13
14#include <QDebug>
15#include <QFuture>
16#include <QFutureWatcher>
17#include <QString>
18#include <QtConcurrentRun>
19#include <QtConcurrentMap>
20#include <QtCore>
21#include <QTimer>
22
23#include "Control.h"
24#include "ControlNet.h"
25#include "FileName.h"
26#include "IString.h"
27#include "Progress.h"
28#include "IException.h"
29
30using std::cerr;
31using std::cout;
32using std::swap;
33
34namespace Isis {
35
40 nullify();
41
42 m_mappedRunning = false;
43
44 m_progressBar = new ProgressBar("Reading Control Nets");
45 m_watcher = new QFutureWatcher<Control *>;
46
47 initProgress();
48
49 connect(m_watcher, SIGNAL(finished()), this, SLOT(mappedFinished()));
50 }
51
52
57
58 if (m_watcher)
59 {
60 m_watcher->cancel();
61 m_watcher->waitForFinished();
62 }
63
64 delete m_watcher;
65 m_watcher = NULL;
66
67 delete m_progressBar;
68 }
69
70
71 ProgressBar *ConcurrentControlNetReader::progressBar() {
72 return m_progressBar;
73 }
74
75
79 void ConcurrentControlNetReader::read(QString filename) {
80
81 m_backlog.append(filename);
82
83 if (!m_progressBar.isNull()) {
84 m_progressBar->setRange(0, m_progressBar->maximum() + 1);
85 }
86
87 start();
88 }
89
90
95
96 m_backlog.append(filenames);
97
98 if (!m_progressBar.isNull()) {
99 m_progressBar->setRange(0, m_progressBar->maximum() + filenames.size());
100 }
101
102 start();
103 }
104
105
112
113
114 void ConcurrentControlNetReader::initProgress() {
115 if (m_progressBar) {
116 m_progressBar->setVisible(false);
117 m_progressBar->setRange(0, 100);
118 m_progressBar->setValue(0);
119 }
120 }
121
122
123 void ConcurrentControlNetReader::start() {
124
125 if (!m_backlog.isEmpty() && !m_mappedRunning) {
126
127 QList< QPair<FileName, Progress *> > functorInput;
128 foreach (QString backlogFileName, m_backlog) {
129 Progress *progress = new Progress;
130 progress->DisableAutomaticDisplay();
131 m_progress.append(progress);
132
133 functorInput.append(qMakePair(FileName(backlogFileName), progress));
134 }
135
136 QFuture<Control *> networks = QtConcurrent::mapped(functorInput,
137 FileNameToControlFunctor(QThread::currentThread()));
138
139 try {
140 networks.result();
141 }
142 catch (IException &e) {
143 throw e;
144 }
145
146 if (!m_progressBar.isNull()) {
147 m_progressBar->setVisible(true);
148 }
149
150 delete m_progressUpdateTimer;
151
152 m_watcher->setFuture(networks);
153 m_mappedRunning = true;
154 m_backlog.clear();
155
156 m_progressUpdateTimer = new QTimer;
157 connect(m_progressUpdateTimer, SIGNAL(timeout()),
158 this, SLOT(updateProgressValue()));
159 m_progressUpdateTimer->start(100);
160 }
161 }
162
163
164 void ConcurrentControlNetReader::updateProgressValue() {
165 if (!m_mappedRunning) {
166 foreach (Progress *progress, m_progress) {
167 delete progress;
168 }
169
170 m_progress.clear();
171 }
172
173 int progressMin = 0;
174 int progressMax = (m_progress.count() + m_backlog.count()) * 1000;
175 int progressCurrent = 0;
176
177 foreach (Progress *progress, m_progress) {
178 if (progress->MaximumSteps()) {
179 if (progress->CurrentStep() < progress->MaximumSteps()) {
180 double progressPercent = progress->CurrentStep() / (double)progress->MaximumSteps();
181
182 progressCurrent += qFloor(progressPercent * 1000);
183 }
184 else {
185 progressCurrent += 1000;
186 }
187 }
188 }
189
190 if (m_progressBar) {
191 if (progressMax > 0) {
192 m_progressBar->setRange(progressMin, progressMax);
193 m_progressBar->setValue(progressCurrent);
194 }
195 else {
196 m_progressBar->setRange(0, 100);
197 m_progressBar->setValue(100);
198 }
199 }
200 }
201
202
203 void ConcurrentControlNetReader::mappedFinished() {
204 m_mappedRunning = false;
205
206 delete m_progressUpdateTimer;
207 updateProgressValue();
208
209 QList<Control *> networks(m_watcher->future().results());
210 emit networksReady(networks);
211
212 if (!m_backlog.isEmpty()) {
213 start();
214 }
215 else {
216 initProgress();
217 }
218 }
219
220
221 ConcurrentControlNetReader::FileNameToControlFunctor::FileNameToControlFunctor(
222 QThread *targetThread) {
223 m_targetThread = targetThread;
224 }
225
226
227 ConcurrentControlNetReader::FileNameToControlFunctor::FileNameToControlFunctor(
228 const FileNameToControlFunctor & other) {
229 m_targetThread = other.m_targetThread;
230 }
231
232
233 ConcurrentControlNetReader::FileNameToControlFunctor::~FileNameToControlFunctor() {
234 m_targetThread = NULL;
235 }
236
237
238 Control * ConcurrentControlNetReader::FileNameToControlFunctor::operator()(
239 const QPair<FileName, Progress *> &fileNameAndProgress) const {
240
241 QString fileNameString = fileNameAndProgress.first.expanded();
242 Progress *progress = fileNameAndProgress.second;
243
244 ControlNet *newCnet = new ControlNet(fileNameString, progress);
245 Control *result = new Control(newCnet, fileNameString);
246
247 newCnet->setParent(result);
248 result->moveToThread(m_targetThread);
249
250 return result;
251 }
252
253
254 ConcurrentControlNetReader::FileNameToControlFunctor &
255 ConcurrentControlNetReader::FileNameToControlFunctor::operator=(
256 const FileNameToControlFunctor &rhs) {
257 m_targetThread = rhs.m_targetThread;
258 return *this;
259 }
260}
QFutureWatcher< Control * > * m_watcher
provides SIGNALS / SLOTS for FileNameToControlFunctor
void nullify()
Initializes members to NULL.
ConcurrentControlNetReader()
Allocates memory at construction instead of as needed.
~ConcurrentControlNetReader()
This destructor will cancel all running threads and block.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16