workerthread.cpp
1 /********************************************************************************
2  * FARSA Experiments Library *
3  * Copyright (C) 2007-2012 *
4  * Gianluca Massera <emmegian@yahoo.it> *
5  * Stefano Nolfi <stefano.nolfi@istc.cnr.it> *
6  * Tomassino Ferrauto <tomassino.ferrauto@istc.cnr.it> *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
21  ********************************************************************************/
22 
23 #include "workerthread.h"
24 
25 namespace farsa {
26 
27 WorkerThread::WorkerThread( QObject* parent ) :
28  QThread(parent),
29  operations(),
30  mutex(),
31  waitForOperationsToDo(),
32  operation(),
33  quitRequested(false),
34  exceptions() {
35 }
36 
38  foreach (BaseException *e, exceptions) {
39  delete e;
40  }
41 }
42 
43 void WorkerThread::addOperation( ThreadOperation* newOperation, bool deleteAtEnd ) {
44  mutex.lock();
45  operations.enqueue( ThreadOperationInfo( newOperation, deleteAtEnd ) );
46  mutex.unlock();
47  if ( operations.size() == 1 ) {
48  // wake the run thread because now there is something to do
49  waitForOperationsToDo.wakeAll();
50  }
51 }
52 
54  mutex.lock();
55  if ( operation.operation ) {
56  operation.operation->stop();
57  }
58  mutex.unlock();
59 }
60 
62  forever {
63  mutex.lock();
64  // We have to check quitRequested here (not only after waitForOperationsToDo.wait()) because quit() can
65  // be called before run() starts. In that case quitRequested is already true, but we lost the "signal"
66  // that should wake us when on the wait condition and so we would sleep indefinitely
67  if ( quitRequested ) {
68  mutex.unlock();
69  return;
70  }
71  if ( operations.size() == 0 ) {
72  // wait the adding of an operation
73  waitForOperationsToDo.wait( &mutex );
74  }
75  if ( quitRequested ) {
76  mutex.unlock();
77  return;
78  }
79  operation = operations.dequeue();
80  mutex.unlock();
81  try {
82  operation.operation->run();
83  } catch (BaseException& e) {
84  BaseException* cloned = e.clone();
85  exceptions.append(cloned);
86 
87  emit exceptionDuringOperation(cloned);
88  } catch (...) {
90  exceptions.append(e);
91 
93  }
94  mutex.lock();
95  if ( operation.deleteAtEnd ) {
96  delete operation.operation;
97  }
98  operation.operation = NULL;
99  mutex.unlock();
100  if ( quitRequested ) {
101  return;
102  }
103  }
104 }
105 
107  mutex.lock();
108  quitRequested = true;
109  mutex.unlock();
111  waitForOperationsToDo.wakeAll();
112  wait();
113 }
114 
116 {
117  mutex.lock();
118  bool ret = (operation.operation != NULL);
119  mutex.unlock();
120 
121  return ret;
122 }
123 
124 } // end namespace farsa