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 #include "utilitiesexceptions.h"
25 
26 namespace farsa {
27 
28 WorkerThread::WorkerThread( QObject* parent ) :
29  QThread(parent),
30  operations(),
31  mutex(),
32  waitForOperationsToDo(),
33  waitForOperationsToFinish(),
34  operation(),
35  quitRequested(false),
36  exceptions() {
37 }
38 
40  foreach (BaseException *e, exceptions) {
41  delete e;
42  }
43 }
44 
45 void WorkerThread::addOperation( ThreadOperation* newOperation, bool deleteAtEnd ) {
46  mutex.lock();
47  operations.enqueue( ThreadOperationInfo( newOperation, deleteAtEnd ) );
48  mutex.unlock();
49  if ( operations.size() == 1 ) {
50  // wake the run thread because now there is something to do
51  waitForOperationsToDo.wakeAll();
52  }
53 }
54 
56  mutex.lock();
57  if ( operation.operation ) {
58  operation.operation->stop();
59  }
60  if (wait) {
61  waitForOperationsToFinish.wait(&mutex);
62  }
63  mutex.unlock();
64 }
65 
67  forever {
68  mutex.lock();
69  // We have to check quitRequested here (not only after waitForOperationsToDo.wait()) because quit() can
70  // be called before run() starts. In that case quitRequested is already true, but we lost the "signal"
71  // that should wake us when on the wait condition and so we would sleep indefinitely
72  if ( quitRequested ) {
73  mutex.unlock();
74  return;
75  }
76  if ( operations.size() == 0 ) {
77  // wait the adding of an operation
78  waitForOperationsToDo.wait( &mutex );
79  }
80  if ( quitRequested ) {
81  mutex.unlock();
82  return;
83  }
84  operation = operations.dequeue();
85  mutex.unlock();
86  try {
87  operation.operation->run();
88  } catch (BaseException& e) {
89  BaseException* cloned = e.clone();
90  exceptions.append(cloned);
91 
92  emit exceptionDuringOperation(cloned);
93  } catch (std::exception& e) {
95  exceptions.append(cloned);
96 
97  emit exceptionDuringOperation(cloned);
98  } catch (...) {
100  exceptions.append(e);
101 
102  emit exceptionDuringOperation(e);
103  }
104  mutex.lock();
105  if ( operation.deleteAtEnd ) {
106  delete operation.operation;
107  }
108  operation.operation = NULL;
109  mutex.unlock();
110  waitForOperationsToFinish.wakeAll();
111  if ( quitRequested ) {
112  return;
113  }
114  }
115 }
116 
118  mutex.lock();
119  quitRequested = true;
120  mutex.unlock();
121  stopCurrentOperation(false); // No need to wait on operation to finish, we wait for the entire thread to complete
122  waitForOperationsToDo.wakeAll();
123  wait();
124 }
125 
127 {
128  mutex.lock();
129  bool ret = (operation.operation != NULL);
130  mutex.unlock();
131 
132  return ret;
133 }
134 
135 } // end namespace farsa
void run()
implement the main run routine
~WorkerThread()
destructor
void stopCurrentOperation(bool wait)
Stop the current operation.
void exceptionDuringOperation(farsa::BaseException *e)
The signal emitted when a ThreadOperation throws as exception.
void quit()
stop the current operation and quit from the thread terminating its cycle.
A macro to deprecate functions.
An exception thrown when we catch standard library exceptions in a worker thread. ...
interface for describing an operation to do for the WorkerThread
Definition: workerthread.h:108
The exception stored when an unknown exception is thrown by a ThreadOperation.
Definition: workerthread.h:44
bool operationRunning()
Returns true if an operation is running.
WorkerThread(QObject *parent)
constructor
void addOperation(ThreadOperation *operation, bool deleteAtEnd=true)
Add an operation to the queue.