itom  4.1.0
sharedStructuresQt.h
1 /* ********************************************************************
2  itom software
3  URL: http://www.uni-stuttgart.de/ito
4  Copyright (C) 2020, 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) :
78  m_numOfListeners(numberOfListeners),
79  m_instCounter(numberOfListeners + 1),
80  m_enableDelete(false),
81  m_callerStillWaiting(true),
82  returnValue(ito::retOk)
83  {
84  QMutexLocker mutexLocker(&internalMutex);
85  m_pSemaphore = new QSemaphore(m_numOfListeners);
86  m_pSemaphore->acquire(m_numOfListeners);
87  }
88 
90  /*
91  \sa ItomSharedSemaphore::deleteSemaphore
92  */
94  {
95  Q_ASSERT_X(m_enableDelete, "~ItomSharedSemaphore", "it is not allowed to directly destroy ItomSharedSemaphore. Always use ItomSharedSemaphore::deleteSemaphore(...)");
96 
97  if(m_pSemaphore->available() < m_numOfListeners)
98  {
99  m_pSemaphore->release( m_numOfListeners - m_pSemaphore->available());
100  qDebug("ItomSharedSemaphore is not fully available at moment of destruction");
101  }
102  if (m_pSemaphore)
103  delete m_pSemaphore;
104  m_pSemaphore = NULL;
105  }
106 
108  /*
109  The timeout time is indicated in milliseconds, a value equal to -1 means that no timeout is set and this methods
110  only returns if the called method released the semaphore. In the constructor of ItomSharedSemaphore, the semaphore
111  has been locked with a number equal to the number of listeners, which usually is 1. The semaphore is unlocked, if
112  every listener releases the semaphore once (\sa release).
113 
114  A possible timeout is indicated by a debug-warning in the output window of the IDE.
115 
116  @param [in] timeout in ms [-1 : no timeout]
117  @return true if caller (listener) released the lock within the given timeout time, false if timeout expired
118  @sa release, waitAndProcessEvents
119  */
120  inline bool wait(int timeout)
121  {
122  bool success;
123 
124  if (timeout >= 0)
125  {
126  success = m_pSemaphore->tryAcquire(m_numOfListeners, timeout);
127  }
128  else
129  {
130  //due to a bug in linux (at least CentOS 7), tryAcquire causes a crash for infinite timeouts.
131  //therefore, we use the specific case here, to handle these cases.
132  m_pSemaphore->acquire(m_numOfListeners);
133  success = true;
134  }
135 
136  QMutexLocker mutexLocker(&internalMutex);
137  if(success == false)
138  {
139  qDebug() << "ItomSharedSemaphore run into a timeout. Number of attempted listeners: " << m_numOfListeners << ", already freed: " << m_pSemaphore->available();
140  }
141  else
142  {
143  m_pSemaphore->release(m_numOfListeners);
144  }
145 
146  m_callerStillWaiting = false;
147 
148  return success;
149  }
150 
152  /*
153  The timeout time is indicated in milliseconds, a value equal to -1 means that no timeout is set and this methods
154  only returns if the called method released the semaphore. In the constructor of ItomSharedSemaphore, the semaphore
155  has been locked with a number equal to the number of listeners, which usually is 1. The semaphore is unlocked, if
156  every listener releases the semaphore once (\sa release).
157 
158  The only difference between this method and wait is, that this implementation continuously allows
159  processing events in the event loop of the waiting thread. The type of allowed events is set by flags.
160 
161  A possible timeout is indicated by a debug-warning in the output window of the IDE.
162 
163  @param [in] timeout in ms [-1 : no timeout]
164  @param [in] flags is the type of allowed events that can be processed in the calling thread during the wait.
165  @return true if caller (listener) released the lock within the given timeout time, false if timeout expired
166  @sa release, wait
167  */
168  bool waitAndProcessEvents(int timeout, QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents);
169 
171  /*
172  the called method in another thread must release the semaphore as soon as possible such that the caller can continue
173  */
174  inline void release() { /*qDebug() << "semaphore release";*/ m_pSemaphore->release(1); }
175 
177  /*
178  @return true if semaphore is still locked, else false
179  */
180  inline int available() const { return m_pSemaphore->available(); }
181 
183  /*
184  this method is not 100% thread-safe, that means it might occure, that the wait-method of the caller drops into the timeout
185  during the call to the method isCallerStillWaiting. Therefore consider this method as pure information.
186 
187  @return true if caller-method is still waiting (in \sa wait-method) that all listeners are calling the release method
188  in order to free the lock of the semaphore. else: false
189  */
190  inline bool isCallerStillWaiting() { QMutexLocker mutexLocker(&internalMutex); return m_callerStillWaiting; }
191 
193  //
194  // Every listener and the caller-method must call this static method with the pointer to the corresponding ItomSharedSemaphore
195  // in order to guarantee the final deletion of the semaphore, if it is not needed any more by any participating method (caller or listener).
196  //
197  // In every listener method (called method) you should call this method after you released the semaphore (\sa release).
198  // The ItomSharedSemaphore consists of a internal reference counter, which is set to the number of listeners plus 1 at
199  // construction time. Every call to deleteSemaphore decreases this counter and if this counter drops to zero, no method
200  // uses the semaphore any more such that it is safely deleted. Be careful that you don't access the semaphore in a method
201  // where you already called deleteSemaphore with the semaphore-pointer as parameter.
202  //
203  // In order to simplify the handling of ItomSharedSemaphore consider to used ItomSharedSemaphoreLocker.
204 
205  inline void deleteSemaphore(void)
206  {
207  QMutexLocker mutexLocker(&internalMutex);
208 
209  m_instCounter --;
210  if(m_instCounter <= 0)
211  {
212  m_enableDelete = true;
213  mutexLocker.unlock();
214  delete this;
215  return;
216  }
217 
218  return;
219  }
220 
222 };
223 
224 
233 {
234  public:
236  inline ItomSharedSemaphoreLocker(ItomSharedSemaphore* semaphore) : m_semaphore(semaphore) {}
237 
240 
243  {
244  if(m_semaphore)
245  {
247  m_semaphore = NULL;
248  }
249  }
250 
252  inline ItomSharedSemaphore* getSemaphore() const { return m_semaphore; }
253 
256 
258  /*
259  If this locker already guards an instance of ItomSharedSemaphore its reference counter is decremented first. \sa ItomSharedSemaphore::deleteSemaphore.
260  */
262  {
263  if(m_semaphore)
264  {
266  m_semaphore = NULL;
267  }
268  m_semaphore = newSemaphoreInstance;
269  return *this;
270  }
271 
272  private:
273  inline ItomSharedSemaphoreLocker(ItomSharedSemaphoreLocker & /*other*/ ) { /* forbidden */ }
274  inline ItomSharedSemaphoreLocker & operator = (const ItomSharedSemaphoreLocker & /*other*/ ) { return *this; /* forbidden */ }
276 };
277 
278 //} //end namespace ito
279 
280 #endif //#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC)
281 
282 #endif
~ItomSharedSemaphore()
destructor (do not call directly, instead free the semaphore by ItomSharedSemaphore::deleteSemaphore ...
Definition: sharedStructuresQt.h:93
Locker-class for ItomSharedSemaphore. The functionality is equal to QMutexLocker in Qt...
Definition: sharedStructuresQt.h:232
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:205
~ItomSharedSemaphoreLocker()
destructor.
Definition: sharedStructuresQt.h:242
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:236
ItomSharedSemaphore * getSemaphore() const
returns the pointer to the guarded ItomSharedSemaphore.
Definition: sharedStructuresQt.h:252
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:190
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:239
ItomSharedSemaphore(int numberOfListeners=1)
constructor
Definition: sharedStructuresQt.h:77
ItomSharedSemaphoreLocker & operator=(ItomSharedSemaphore *newSemaphoreInstance)
assigns another ItomSharedSemaphore to this locker.
Definition: sharedStructuresQt.h:261
ItomSharedSemaphore * m_semaphore
Definition: sharedStructuresQt.h:275
ItomSharedSemaphore * operator->() const
returns the pointer to the guarded ItomSharedSemaphore.
Definition: sharedStructuresQt.h:255
int m_numOfListeners
Definition: sharedStructuresQt.h:63
int available() const
checks whether the semaphore is still locked or not
Definition: sharedStructuresQt.h:180
void release()
decreases the number of locks by one
Definition: sharedStructuresQt.h:174
ito::RetVal returnValue
Definition: sharedStructuresQt.h:221
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:120