itom  3.0.0
sharedStructuresQt.h
1 /* ********************************************************************
2  itom software
3  URL: http://www.uni-stuttgart.de/ito
4  Copyright (C) 2016, Institut fuer Technische Optik (ITO),
5  Universitaet Stuttgart, Germany
6 
7  This file is part of itom and its software development toolkit (SDK).
8 
9  itom is free software; you can redistribute it and/or modify it
10  under the terms of the GNU Library General Public Licence as published by
11  the Free Software Foundation; either version 2 of the Licence, or (at
12  your option) any later version.
13 
14  In addition, as a special exception, the Institut fuer Technische
15  Optik (ITO) gives you certain additional rights.
16  These rights are described in the ITO LGPL Exception version 1.0,
17  which can be found in the file LGPL_EXCEPTION.txt in this package.
18 
19  itom is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
22  General Public Licence for more details.
23 
24  You should have received a copy of the GNU Library General Public License
25  along with itom. If not, see <http://www.gnu.org/licenses/>.
26 *********************************************************************** */
27 
28 #ifndef SHAREDSTRUCTURES_QT_H
29 #define SHAREDSTRUCTURES_QT_H
30 
31 #include "commonGlobal.h"
32 #include <qmutex.h>
33 #include <qsemaphore.h>
34 #include <qdebug.h>
35 #include <qeventloop.h>
36 #include <qmap.h>
37 #include <qstring.h>
38 
39 #include "sharedStructures.h"
40 
41 //definition of some tags for signals and slots
42 #ifndef Q_MOC_RUN
43  //the following tags can be placed before the definition of slots and signals, they are then obtainable via the tag() method of QMetaMethod.
44 
45  //place ITOM_PYNOTACCESSIBLE before the definition of a method to not show this method in auto-parsed listings that are dedicated to python usage.
46  #define ITOM_PYNOTACCESSIBLE
47 #endif
48 
49 #if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) //only moc this file in itomCommonQtLib but not in other libraries or executables linking against this itomCommonQtLib
50 
51 typedef QMap<QString, ito::Param> ParamMap;
52 typedef ParamMap::iterator ParamMapIterator;
53 
54 //namespace ito
55 //{
56 
57 class ITOMCOMMONQT_EXPORT ItomSharedSemaphore
58 {
59  private:
60  QSemaphore *m_pSemaphore;
65  QMutex internalMutex;
67  public:
69 
77  inline ItomSharedSemaphore(int numberOfListeners = 1) : m_numOfListeners(numberOfListeners), m_instCounter(numberOfListeners + 1), m_enableDelete(false), m_callerStillWaiting(true), returnValue(ito::retOk)
78  {
79  internalMutex.lock();
80  m_pSemaphore = new QSemaphore(m_numOfListeners);
81  m_pSemaphore->acquire(m_numOfListeners);
82  internalMutex.unlock();
83  }
84 
86  /*
87  \sa ItomSharedSemaphore::deleteSemaphore
88  */
90  {
91  Q_ASSERT_X(m_enableDelete, "~ItomSharedSemaphore", "it is not allowed to directly destroy ItomSharedSemaphore. Always use ItomSharedSemaphore::deleteSemaphore(...)");
92 
93  if(m_pSemaphore->available() < m_numOfListeners)
94  {
95  m_pSemaphore->release( m_numOfListeners - m_pSemaphore->available());
96  qDebug("ItomSharedSemaphore is not fully available at moment of destruction");
97  }
98  if (m_pSemaphore)
99  delete m_pSemaphore;
100  m_pSemaphore = NULL;
101  }
102 
104  /*
105  The timeout time is indicated in milliseconds, a value equal to -1 means that no timeout is set and this methods
106  only returns if the called method released the semaphore. In the constructor of ItomSharedSemaphore, the semaphore
107  has been locked with a number equal to the number of listeners, which usually is 1. The semaphore is unlocked, if
108  every listener releases the semaphore once (\sa release).
109 
110  A possible timeout is indicated by a debug-warning in the output window of the IDE.
111 
112  @param [in] timeout in ms [-1 : no timeout]
113  @return true if caller (listener) released the lock within the given timeout time, false if timeout expired
114  @sa release, waitAndProcessEvents
115  */
116  inline bool wait(int timeout)
117  {
118  bool temp;
119  temp = m_pSemaphore->tryAcquire(m_numOfListeners, timeout);
120 
121  QMutexLocker mutexLocker(&internalMutex);
122  if(temp == false)
123  {
124  qDebug() << "ItomSharedSemaphore run into a timeout. Number of attempted listeners: " << m_numOfListeners << ", already freed: " << m_pSemaphore->available();
125  }
126  else
127  {
128  m_pSemaphore->release(m_numOfListeners);
129  }
130 
131  m_callerStillWaiting = false;
132 
133  return temp;
134  }
135 
137  /*
138  The timeout time is indicated in milliseconds, a value equal to -1 means that no timeout is set and this methods
139  only returns if the called method released the semaphore. In the constructor of ItomSharedSemaphore, the semaphore
140  has been locked with a number equal to the number of listeners, which usually is 1. The semaphore is unlocked, if
141  every listener releases the semaphore once (\sa release).
142 
143  The only difference between this method and wait is, that this implementation continuously allows
144  processing events in the event loop of the waiting thread. The type of allowed events is set by flags.
145 
146  A possible timeout is indicated by a debug-warning in the output window of the IDE.
147 
148  @param [in] timeout in ms [-1 : no timeout]
149  @param [in] flags is the type of allowed events that can be processed in the calling thread during the wait.
150  @return true if caller (listener) released the lock within the given timeout time, false if timeout expired
151  @sa release, wait
152  */
153  bool waitAndProcessEvents(int timeout, QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents);
154 
156  /*
157  the called method in another thread must release the semaphore as soon as possible such that the caller can continue
158  */
159  inline void release() { /*qDebug() << "semaphore release";*/ m_pSemaphore->release(1); }
160 
162  /*
163  @return true if semaphore is still locked, else false
164  */
165  inline int available() const { return m_pSemaphore->available(); }
166 
168  /*
169  this method is not 100% thread-safe, that means it might occure, that the wait-method of the caller drops into the timeout
170  during the call to the method isCallerStillWaiting. Therefore consider this method as pure information.
171 
172  @return true if caller-method is still waiting (in \sa wait-method) that all listeners are calling the release method
173  in order to free the lock of the semaphore. else: false
174  */
175  inline bool isCallerStillWaiting() { QMutexLocker mutexLocker(&internalMutex); return m_callerStillWaiting; }
176 
178  //
179  // Every listener and the caller-method must call this static method with the pointer to the corresponding ItomSharedSemaphore
180  // in order to guarantee the final deletion of the semaphore, if it is not needed any more by any participating method (caller or listener).
181  //
182  // In every listener method (called method) you should call this method after you released the semaphore (\sa release).
183  // The ItomSharedSemaphore consists of a internal reference counter, which is set to the number of listeners plus 1 at
184  // construction time. Every call to deleteSemaphore decreases this counter and if this counter drops to zero, no method
185  // uses the semaphore any more such that it is safely deleted. Be careful that you don't access the semaphore in a method
186  // where you already called deleteSemaphore with the semaphore-pointer as parameter.
187  //
188  // In order to simplify the handling of ItomSharedSemaphore consider to used ItomSharedSemaphoreLocker.
189 
190  inline void deleteSemaphore(void)
191  {
192  QMutexLocker mutexLocker(&internalMutex);
193 
194  m_instCounter --;
195  if(m_instCounter <= 0)
196  {
197  m_enableDelete = true;
198  mutexLocker.unlock();
199  delete this;
200  return;
201  }
202 
203  return;
204  }
205 
207 };
208 
209 
218 {
219  public:
221  inline ItomSharedSemaphoreLocker(ItomSharedSemaphore* semaphore) : m_semaphore(semaphore) {}
222 
224  inline ItomSharedSemaphoreLocker() : m_semaphore(NULL) {}
225 
228  {
229  if(m_semaphore)
230  {
231  m_semaphore->deleteSemaphore();
232  m_semaphore = NULL;
233  }
234  }
235 
237  inline ItomSharedSemaphore* getSemaphore() const { return m_semaphore; }
238 
240  ItomSharedSemaphore* operator ->() const { return m_semaphore; }
241 
243  /*
244  If this locker already guards an instance of ItomSharedSemaphore its reference counter is decremented first. \sa ItomSharedSemaphore::deleteSemaphore.
245  */
246  inline ItomSharedSemaphoreLocker & operator = (ItomSharedSemaphore *newSemaphoreInstance)
247  {
248  if(m_semaphore)
249  {
250  m_semaphore->deleteSemaphore();
251  m_semaphore = NULL;
252  }
253  m_semaphore = newSemaphoreInstance;
254  return *this;
255  }
256 
257  private:
258  inline ItomSharedSemaphoreLocker(ItomSharedSemaphoreLocker & /*other*/ ) { /* forbidden */ }
259  inline ItomSharedSemaphoreLocker & operator = (const ItomSharedSemaphoreLocker & /*other*/ ) { return *this; /* forbidden */ }
261 };
262 
263 //} //end namespace ito
264 
265 #endif //#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC)
266 
267 #endif
~ItomSharedSemaphore()
destructor (do not call directly, instead free the semaphore by ItomSharedSemaphore::deleteSemaphore ...
Definition: sharedStructuresQt.h:89
Locker-class for ItomSharedSemaphore. The functionality is equal to QMutexLocker in Qt...
Definition: sharedStructuresQt.h:217
QSemaphore * m_pSemaphore
Definition: sharedStructuresQt.h:60
void deleteSemaphore(void)
static method to decrease the reference counter of any ItomSharedSemaphore or delete it if the refere...
Definition: sharedStructuresQt.h:190
~ItomSharedSemaphoreLocker()
destructor.
Definition: sharedStructuresQt.h:227
Class for managing status values (like errors or warning)
Definition: retVal.h:54
ItomSharedSemaphoreLocker(ItomSharedSemaphore *semaphore)
constructor with ItomSharedSemaphore-pointer as parameter. This semaphore will be guarded by this loc...
Definition: sharedStructuresQt.h:221
ItomSharedSemaphore * getSemaphore() const
returns the pointer to the guarded ItomSharedSemaphore.
Definition: sharedStructuresQt.h:237
Definition: apiFunctionsGraph.cpp:39
int m_instCounter
Definition: sharedStructuresQt.h:61
bool m_enableDelete
Definition: sharedStructuresQt.h:62
bool isCallerStillWaiting()
indicates whether caller-method is still waiting that the lock is released by the listener(s)...
Definition: sharedStructuresQt.h:175
semaphore which can be used for asychronous thread communication. By using this class it is possible ...
Definition: sharedStructuresQt.h:57
QMutex internalMutex
Definition: sharedStructuresQt.h:65
ItomSharedSemaphoreLocker()
empty constructor. The locker will not guard any semaphore yet.
Definition: sharedStructuresQt.h:224
ItomSharedSemaphore(int numberOfListeners=1)
constructor
Definition: sharedStructuresQt.h:77
ItomSharedSemaphore * m_semaphore
Definition: sharedStructuresQt.h:260
int m_numOfListeners
Definition: sharedStructuresQt.h:63
int available() const
checks whether the semaphore is still locked or not
Definition: sharedStructuresQt.h:165
void release()
decreases the number of locks by one
Definition: sharedStructuresQt.h:159
ito::RetVal returnValue
Definition: sharedStructuresQt.h:206
bool m_callerStillWaiting
Definition: sharedStructuresQt.h:64
bool wait(int timeout)
The call of this method returns if a certain timeout has been expired or every listener released the ...
Definition: sharedStructuresQt.h:116