itom 2.2.1
|
00001 /* ******************************************************************** 00002 itom software 00003 URL: http://www.uni-stuttgart.de/ito 00004 Copyright (C) 2016, Institut fuer Technische Optik (ITO), 00005 Universitaet Stuttgart, Germany 00006 00007 This file is part of itom and its software development toolkit (SDK). 00008 00009 itom is free software; you can redistribute it and/or modify it 00010 under the terms of the GNU Library General Public Licence as published by 00011 the Free Software Foundation; either version 2 of the Licence, or (at 00012 your option) any later version. 00013 00014 In addition, as a special exception, the Institut fuer Technische 00015 Optik (ITO) gives you certain additional rights. 00016 These rights are described in the ITO LGPL Exception version 1.0, 00017 which can be found in the file LGPL_EXCEPTION.txt in this package. 00018 00019 itom is distributed in the hope that it will be useful, but 00020 WITHOUT ANY WARRANTY; without even the implied warranty of 00021 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library 00022 General Public Licence for more details. 00023 00024 You should have received a copy of the GNU Library General Public License 00025 along with itom. If not, see <http://www.gnu.org/licenses/>. 00026 *********************************************************************** */ 00027 00028 #ifndef SHAREDSTRUCTURES_QT_H 00029 #define SHAREDSTRUCTURES_QT_H 00030 00031 #include "commonGlobal.h" 00032 #include <qmutex.h> 00033 #include <qsemaphore.h> 00034 #include <qdebug.h> 00035 #include <qeventloop.h> 00036 #include <qmap.h> 00037 #include <qstring.h> 00038 00039 #include "sharedStructures.h" 00040 00041 //definition of some tags for signals and slots 00042 #ifndef Q_MOC_RUN 00043 //the following tags can be placed before the definition of slots and signals, they are then obtainable via the tag() method of QMetaMethod. 00044 00045 //place ITOM_PYNOTACCESSIBLE before the definition of a method to not show this method in auto-parsed listings that are dedicated to python usage. 00046 #define ITOM_PYNOTACCESSIBLE 00047 #endif 00048 00049 #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 00050 00051 typedef QMap<QString, ito::Param> ParamMap; 00052 typedef ParamMap::iterator ParamMapIterator; 00053 00054 //namespace ito 00055 //{ 00056 00057 class ITOMCOMMONQT_EXPORT ItomSharedSemaphore 00058 { 00059 private: 00060 QSemaphore *m_pSemaphore; 00061 int m_instCounter; 00062 bool m_enableDelete; 00063 int m_numOfListeners; 00064 bool m_callerStillWaiting; 00065 QMutex internalMutex; 00067 public: 00069 00077 inline ItomSharedSemaphore(int numberOfListeners = 1) : m_numOfListeners(numberOfListeners), m_instCounter(numberOfListeners + 1), m_enableDelete(false), m_callerStillWaiting(true), returnValue(ito::retOk) 00078 { 00079 internalMutex.lock(); 00080 m_pSemaphore = new QSemaphore(m_numOfListeners); 00081 m_pSemaphore->acquire(m_numOfListeners); 00082 internalMutex.unlock(); 00083 } 00084 00086 /* 00087 \sa ItomSharedSemaphore::deleteSemaphore 00088 */ 00089 inline ~ItomSharedSemaphore() 00090 { 00091 Q_ASSERT_X(m_enableDelete, "~ItomSharedSemaphore", "it is not allowed to directly destroy ItomSharedSemaphore. Always use ItomSharedSemaphore::deleteSemaphore(...)"); 00092 00093 if(m_pSemaphore->available() < m_numOfListeners) 00094 { 00095 m_pSemaphore->release( m_numOfListeners - m_pSemaphore->available()); 00096 qDebug("ItomSharedSemaphore is not fully available at moment of destruction"); 00097 } 00098 delete m_pSemaphore; 00099 m_pSemaphore = NULL; 00100 } 00101 00103 /* 00104 The timeout time is indicated in milliseconds, a value equal to -1 means that no timeout is set and this methods 00105 only returns if the called method released the semaphore. In the constructor of ItomSharedSemaphore, the semaphore 00106 has been locked with a number equal to the number of listeners, which usually is 1. The semaphore is unlocked, if 00107 every listener releases the semaphore once (\sa release). 00108 00109 A possible timeout is indicated by a debug-warning in the output window of the IDE. 00110 00111 @param [in] timeout in ms [-1 : no timeout] 00112 @return true if caller (listener) released the lock within the given timeout time, false if timeout expired 00113 @sa release, waitAndProcessEvents 00114 */ 00115 inline bool wait(int timeout) 00116 { 00117 bool temp; 00118 temp = m_pSemaphore->tryAcquire(m_numOfListeners, timeout); 00119 00120 QMutexLocker mutexLocker(&internalMutex); 00121 if(temp == false) 00122 { 00123 qDebug() << "ItomSharedSemaphore run into a timeout. Number of attempted listeners: " << m_numOfListeners << ", already freed: " << m_pSemaphore->available(); 00124 } 00125 else 00126 { 00127 m_pSemaphore->release(m_numOfListeners); 00128 } 00129 00130 m_callerStillWaiting = false; 00131 00132 return temp; 00133 } 00134 00136 /* 00137 The timeout time is indicated in milliseconds, a value equal to -1 means that no timeout is set and this methods 00138 only returns if the called method released the semaphore. In the constructor of ItomSharedSemaphore, the semaphore 00139 has been locked with a number equal to the number of listeners, which usually is 1. The semaphore is unlocked, if 00140 every listener releases the semaphore once (\sa release). 00141 00142 The only difference between this method and wait is, that this implementation continuously allows 00143 processing events in the event loop of the waiting thread. The type of allowed events is set by flags. 00144 00145 A possible timeout is indicated by a debug-warning in the output window of the IDE. 00146 00147 @param [in] timeout in ms [-1 : no timeout] 00148 @param [in] flags is the type of allowed events that can be processed in the calling thread during the wait. 00149 @return true if caller (listener) released the lock within the given timeout time, false if timeout expired 00150 @sa release, wait 00151 */ 00152 bool waitAndProcessEvents(int timeout, QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); 00153 00155 /* 00156 the called method in another thread must release the semaphore as soon as possible such that the caller can continue 00157 */ 00158 inline void release() { /*qDebug() << "semaphore release";*/ m_pSemaphore->release(1); } 00159 00161 /* 00162 @return true if semaphore is still locked, else false 00163 */ 00164 inline int available() const { return m_pSemaphore->available(); } 00165 00167 /* 00168 this method is not 100% thread-safe, that means it might occure, that the wait-method of the caller drops into the timeout 00169 during the call to the method isCallerStillWaiting. Therefore consider this method as pure information. 00170 00171 @return true if caller-method is still waiting (in \sa wait-method) that all listeners are calling the release method 00172 in order to free the lock of the semaphore. else: false 00173 */ 00174 inline bool isCallerStillWaiting() { QMutexLocker mutexLocker(&internalMutex); return m_callerStillWaiting; } 00175 00177 // 00178 // Every listener and the caller-method must call this static method with the pointer to the corresponding ItomSharedSemaphore 00179 // in order to guarantee the final deletion of the semaphore, if it is not needed any more by any participating method (caller or listener). 00180 // 00181 // In every listener method (called method) you should call this method after you released the semaphore (\sa release). 00182 // The ItomSharedSemaphore consists of a internal reference counter, which is set to the number of listeners plus 1 at 00183 // construction time. Every call to deleteSemaphore decreases this counter and if this counter drops to zero, no method 00184 // uses the semaphore any more such that it is safely deleted. Be careful that you don't access the semaphore in a method 00185 // where you already called deleteSemaphore with the semaphore-pointer as parameter. 00186 // 00187 // In order to simplify the handling of ItomSharedSemaphore consider to used ItomSharedSemaphoreLocker. 00188 00189 inline void deleteSemaphore(void) 00190 { 00191 QMutexLocker mutexLocker(&internalMutex); 00192 00193 m_instCounter --; 00194 if(m_instCounter <= 0) 00195 { 00196 m_enableDelete = true; 00197 mutexLocker.unlock(); 00198 delete this; 00199 return; 00200 } 00201 00202 return; 00203 } 00204 00205 ito::RetVal returnValue; 00206 }; 00207 00208 00216 class ItomSharedSemaphoreLocker 00217 { 00218 public: 00220 inline ItomSharedSemaphoreLocker(ItomSharedSemaphore* semaphore) : m_semaphore(semaphore) {} 00221 00223 inline ItomSharedSemaphoreLocker() : m_semaphore(NULL) {} 00224 00226 inline ~ItomSharedSemaphoreLocker() 00227 { 00228 if(m_semaphore) 00229 { 00230 m_semaphore->deleteSemaphore(); 00231 m_semaphore = NULL; 00232 } 00233 } 00234 00236 inline ItomSharedSemaphore* getSemaphore() const { return m_semaphore; } 00237 00239 ItomSharedSemaphore* operator ->() const { return m_semaphore; } 00240 00242 /* 00243 If this locker already guards an instance of ItomSharedSemaphore its reference counter is decremented first. \sa ItomSharedSemaphore::deleteSemaphore. 00244 */ 00245 inline ItomSharedSemaphoreLocker & operator = (ItomSharedSemaphore *newSemaphoreInstance) 00246 { 00247 if(m_semaphore) 00248 { 00249 m_semaphore->deleteSemaphore(); 00250 m_semaphore = NULL; 00251 } 00252 m_semaphore = newSemaphoreInstance; 00253 return *this; 00254 } 00255 00256 private: 00257 inline ItomSharedSemaphoreLocker(ItomSharedSemaphoreLocker & /*other*/ ) { /* forbidden */ } 00258 inline ItomSharedSemaphoreLocker & operator = (const ItomSharedSemaphoreLocker & /*other*/ ) { return *this; /* forbidden */ } 00259 ItomSharedSemaphore* m_semaphore; 00260 }; 00261 00262 //} //end namespace ito 00263 00264 #endif //#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) 00265 00266 #endif