Isis 3 Programmer Reference
CubeDataThreadTester.cpp
1 #include "CubeDataThreadTester.h"
2 
3 #include <iostream>
4 
5 #include <QMap>
6 #include <QMutex>
7 #include <QReadWriteLock>
8 #include <QPair>
9 #include <QVector>
10 
11 #include "CubeDataThread.h"
12 #include "IString.h"
13 #include "FileName.h"
14 #include "Brick.h"
15 #include "Cube.h"
16 
17 using namespace std;
18 using namespace Isis;
19 
20 namespace Isis {
27  CubeDataThreadTester::CubeDataThreadTester(CubeDataThread *testObject) :
28  QThread() {
29  p_cachedDoneBricks = NULL;
30  p_cubeDataThread = testObject;
31  p_numTestsDone = 0;
32  p_execStarted = false;
33  p_notifyDone = true;
34 
36 
37  start();
38  moveToThread(this);
39  }
40 
41 
47  connect(this,
48  SIGNAL(RequestReadCube(int, int, int, int, int, int, void *)),
50  SLOT(ReadCube(int, int, int, int, int, int, void *)));
51 
52  connect(this,
53  SIGNAL(RequestReadWriteCube(int, int, int, int, int, int, void *)),
55  SLOT(ReadWriteCube(int, int, int, int, int, int, void *)));
56 
57  connect(this, SIGNAL(NotifyDoneWithData(int, const Isis::Brick *)),
58  p_cubeDataThread, SLOT(DoneWithData(int, const Isis::Brick *)));
59 
60  connect(p_cubeDataThread, SIGNAL(ReadReady(void *, int, const Isis::Brick *)),
61  this, SLOT(ReadBrick(void *, int, const Isis::Brick *)));
62 
63  connect(p_cubeDataThread, SIGNAL(ReadWriteReady(void *, int, Isis::Brick *)),
64  this, SLOT(ReadWriteBrick(void *, int, Isis::Brick *)));
65  }
66 
67 
73  if(!p_execStarted) {
74  QThread::yieldCurrentThread();
75  }
76 
77  QThread::exit(0);
78 
79  wait();
80  }
81 
84  p_execStarted = true;
85  exec();
86  }
87 
94  cout << "=============== Testing Basic Read ===============" << endl;
95  emit RequestReadCube(cubeId, 1, 1, 2, 2, 1, this);
96  }
97 
98 
105  void CubeDataThreadTester::ReadCubeTest2(int cubeId1, int cubeId2) {
106  cout << "=============== Testing Multiple Non-Conflicting Cube Reads " <<
107  "===============" << endl;
108 
109  p_notifyDone = false;
110  emit RequestReadCube(cubeId1, 1, 1, 3, 2, 1, this);
111  emit RequestReadCube(cubeId2, 1, 2, 3, 2, 1, this);
112  }
113 
114 
121  cout << "=============== Testing Exact Overlap Cube Reads ==============="
122  << endl << endl;
123 
124  p_notifyDone = false;
125  emit RequestReadCube(cubeId, 1, 2, 2, 2, 1, this);
126  emit RequestReadCube(cubeId, 1, 2, 2, 2, 1, this);
127  }
128 
129 
136  cout << "=============== Testing Basic R/W ===============" << endl << endl;
137  emit RequestReadWriteCube(cubeId, 1, 1, 2, 2, 1, this);
138  emit RequestReadCube(cubeId, 1, 1, 2, 2, 1, this);
139  }
140 
141 
148  void CubeDataThreadTester::WriteCubeTest2(int cubeId1, int cubeId2) {
149  cout << "=============== Testing Multiple Non-Conflicting Cube R/W " <<
150  "===============" << endl << endl;
151 
152  p_notifyDone = false;
153  emit RequestReadWriteCube(cubeId1, 1, 1, 3, 1, 1, this);
154  emit RequestReadWriteCube(cubeId2, 1, 1, 3, 1, 1, this);
155  }
156 
157 
167  cout << "=============== Testing Conflicting Cube R/W ==============="
168  << endl;
169 
170  p_notifyDone = false;
171  emit RequestReadWriteCube(cubeId, 1, 1, 3, 1, 1, this);
172  emit RequestReadWriteCube(cubeId, 1, 1, 3, 1, 1, this);
173  }
174 
175 
181  cout << " Breaking Deadlock From Test 3" << endl;
182  while(!p_cachedDoneBricks->size()) {
183  msleep(100);
184  }
185 
186  if(p_cachedDoneBricks->size()) {
187  cout << " Notify done with first brick" << endl;
188  emit NotifyDoneWithData((*p_cachedDoneBricks)[0].first,
189  (*p_cachedDoneBricks)[0].second);
190  p_cachedDoneBricks->clear();
191  }
192  }
193 
194 
201  cout << "=============== Testing Change Notification ==============="
202  << endl;
203 
204  connect(p_cubeDataThread,
205  SIGNAL(BrickChanged(int, const Isis::Brick *)),
206  this,
207  SLOT(BrickChanged(int, const Isis::Brick *))
208  );
209 
211  emit RequestReadWriteCube(cubeId, 5, 1, 5, 1, 1, this);
212  }
213 
214 
222  void CubeDataThreadTester::ReadBrick(void *requester, int cubeId,
223  const Isis::Brick *data) {
224  cout << " CubeDataThreadTester::ReadBrick" << endl;
225 
226  cout << " Requester is me? " << ((this == requester) ? "Yes" : "No")
227  << endl;
228 
229  if(this != requester) return;
230 
231  cout << " Data:" << endl;
232 
233  for(int i = 0; i < data->size(); i++) {
234  if(i == 0) cout << " ";
235  if(i % 6 == 6 - 1 && i != data->size() - 1) {
236  cout << data->at(i) << endl << " ";
237  }
238  else if(i == data->size() - 1) {
239  cout << data->at(i) << endl;
240  }
241  else {
242  cout << data->at(i) << "\t";
243  }
244  }
245 
246  cout << endl;
247  if(p_notifyDone) {
248  cout << " Notify done with this brick" << endl;
249  emit NotifyDoneWithData(cubeId, data);
250 
251  if(p_cachedDoneBricks->size()) {
252  cout << " Notify done with first brick" << endl;
253  emit NotifyDoneWithData((*p_cachedDoneBricks)[0].first,
254  (*p_cachedDoneBricks)[0].second);
255  p_cachedDoneBricks->clear();
256  }
257  }
258  else {
260  cache.first = cubeId;
261  cache.second = data;
262 
263  p_cachedDoneBricks->push_back(cache);
264  }
265 
266  p_notifyDone = true;
267  p_numTestsDone ++;
268  }
269 
277  void CubeDataThreadTester::ReadWriteBrick(void *requester, int cubeId,
278  Isis::Brick *data) {
279  cout << " CubeDataThreadTester::ReadWriteBrick" << endl;
280 
281  // This was a nice idea, but has race conditions that are difficult
282  // at best to resolve.
283 
284  //cout << " Managed Bricks in Memory = " <<
285  // p_cubeDataThread->BricksInMemory() << endl;
286 
287  cout << " Changing Brick : Index 0 Becoming 5" << endl;
288  cout << endl;
289 
290  cout << " Old Data: " << endl;
291 
292  for(int i = 0; i < data->size(); i++) {
293  if(i == 0) cout << " ";
294  if(i % 6 == 6 - 1 && i != data->size() - 1) {
295  cout << data->at(i) << endl << " ";
296  }
297  else if(i == data->size() - 1) {
298  cout << data->at(i) << endl;
299  }
300  else {
301  cout << data->at(i) << "\t";
302  }
303  }
304 
305  (*data)[0] = 5;
306 
307  cout << " New Data: " << endl;
308 
309  for(int i = 0; i < data->size(); i++) {
310  if(i == 0) cout << " ";
311  if(i % 6 == 6 - 1 && i != data->size() - 1) {
312  cout << data->at(i) << endl << " ";
313  }
314  else if(i == data->size() - 1) {
315  cout << data->at(i) << endl;
316  }
317  else {
318  cout << data->at(i) << "\t";
319  }
320  }
321 
322  cout << endl;
323 
324  if(p_notifyDone) {
325  cout << " Notify done with this brick" << endl;
326  emit NotifyDoneWithData(cubeId, data);
327 
328  if(p_cachedDoneBricks->size()) {
329  cout << " Notify done with first brick" << endl;
330  emit NotifyDoneWithData((*p_cachedDoneBricks)[0].first,
331  (*p_cachedDoneBricks)[0].second);
332  p_cachedDoneBricks->clear();
333  }
334  }
335  else {
337  cache.first = cubeId;
338  cache.second = data;
339 
340  p_cachedDoneBricks->push_back(cache);
341  }
342 
343  p_notifyDone = true;
344  p_numTestsDone ++;
345  }
346 
347 
354  void CubeDataThreadTester::BrickChanged(int cubeId, const Isis::Brick *data) {
355  cout << " CubeDataThreadTester::BrickChanged" << endl;
356  cout << " Data:" << endl;
357 
358  for(int i = 0; i < data->size(); i++) {
359  if(i == 0) cout << " ";
360  if(i % 6 == 6 - 1 && i != data->size() - 1) {
361  cout << data->at(i) << endl << " ";
362  }
363  else if(i == data->size() - 1) {
364  cout << data->at(i) << endl;
365  }
366  else {
367  cout << data->at(i) << "\t";
368  }
369  }
370 
371  p_numTestsDone ++;
372  emit NotifyDoneWithData(cubeId, data);
373  }
374 };
CubeDataThread * p_cubeDataThread
The data thread being tested.
void WriteCubeTest3BreakDeadlock()
This test breaks the deadlock caused by the third write test.
void ReadBrick(void *requester, int cubeId, const Isis::Brick *data)
This is called when a brick is read.
void RequestReadCube(int cubeId, int startSample, int startLine, int endSample, int endLine, int band, void *caller)
Ask for a brick for reading.
Buffer for containing a three dimensional section of an image.
Definition: Brick.h:61
double at(const int index) const
Returns the value in the shape buffer at the given index.
Definition: Buffer.cpp:247
Namespace for the standard library.
bool p_notifyDone
True if we will notify done on the next brick received for R/W.
void ReadCubeTest(int)
This tests a basic read.
void NotifyChangeTest(int)
This test tests this automatic change notifications.
int size() const
Returns the total number of pixels in the shape buffer.
Definition: Buffer.h:113
void BrickChanged(int cubeId, const Isis::Brick *data)
This is called when a brick is written.
void ReadWriteBrick(void *requester, int cubeId, Isis::Brick *data)
This is called when a brick is given for R/W.
void WriteCubeTest2(int, int)
This tests two non-conflicting writes.
QVector< QPair< int, const Isis::Brick * > > * p_cachedDoneBricks
A list of bricks we haven&#39;t send the done signal for.
void RequestReadWriteCube(int cubeId, int startSample, int startLine, int endSample, int endLine, int band, void *caller)
Ask for a brick for reading and writing.
void ReadCubeTest3(int)
This tests an overlapping read.
void WriteCubeTest3(int)
This tests two conflicting* writes.
Encapsulation of Cube I/O with Change Notifications.
void AddChangeListener()
You must call this method after connecting to the BrickChanged signal, otherwise you are not guarante...
void ReadCubeTest2(int, int)
This tests two basic reads with no conflicts.
int p_numTestsDone
The count of completed tests.
void run()
This thread is centered completely around its event loop.
void Connect()
This connects this class&#39; signals and slots with CubeDataThread&#39;s signals and slots.
void NotifyDoneWithData(int, const Isis::Brick *)
Let the cube data thread know we&#39;re no longer working with a particular brick.
virtual ~CubeDataThreadTester()
This cleans up the cube data thread.
bool p_execStarted
True if this thread is started.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
void WriteCubeTest(int)
This tests a basic write.