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