itom 1.4.0
|
00001 /* ******************************************************************** 00002 itom software 00003 URL: http://www.uni-stuttgart.de/ito 00004 Copyright (C) 2013, Institut für Technische Optik (ITO), 00005 Universität 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 für 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 #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 00042 00043 typedef QMap<QString, ito::Param> ParamMap; 00044 typedef ParamMap::iterator ParamMapIterator; 00045 00046 //namespace ito 00047 //{ 00048 00049 class ITOMCOMMONQT_EXPORT ItomSharedSemaphore 00050 { 00051 private: 00052 QSemaphore *m_pSemaphore; 00053 int m_instCounter; 00054 bool m_enableDelete; 00055 int m_numOfListeners; 00056 bool m_callerStillWaiting; 00057 QMutex internalMutex; 00059 public: 00061 00069 inline ItomSharedSemaphore(int numberOfListeners = 1) : m_numOfListeners(numberOfListeners), m_instCounter(numberOfListeners + 1), m_enableDelete(false), m_callerStillWaiting(true), returnValue(ito::retOk) 00070 { 00071 internalMutex.lock(); 00072 m_pSemaphore = new QSemaphore(m_numOfListeners); 00073 m_pSemaphore->acquire(m_numOfListeners); 00074 internalMutex.unlock(); 00075 } 00076 00078 /* 00079 \sa ItomSharedSemaphore::deleteSemaphore 00080 */ 00081 inline ~ItomSharedSemaphore() 00082 { 00083 Q_ASSERT_X(m_enableDelete, "~ItomSharedSemaphore", "it is not allowed to directly destroy ItomSharedSemaphore. Always use ItomSharedSemaphore::deleteSemaphore(...)"); 00084 00085 if(m_pSemaphore->available() < m_numOfListeners) 00086 { 00087 m_pSemaphore->release( m_numOfListeners - m_pSemaphore->available()); 00088 qDebug("ItomSharedSemaphore is not fully available at moment of destruction"); 00089 } 00090 delete m_pSemaphore; 00091 m_pSemaphore = NULL; 00092 } 00093 00095 /* 00096 The timeout time is indicated in milliseconds, a value equal to -1 means that no timeout is set and this methods 00097 only returns if the called method released the semaphore. In the constructor of ItomSharedSemaphore, the semaphore 00098 has been locked with a number equal to the number of listeners, which usually is 1. The semaphore is unlocked, if 00099 every listener releases the semaphore once (\sa release). 00100 00101 A possible timeout is indicated by a debug-warning in the output window of the IDE. 00102 00103 @param [in] timeout in ms [-1 : no timeout] 00104 @return true if caller (listener) released the lock within the given timeout time, false if timeout expired 00105 @sa release, waitAndProcessEvents 00106 */ 00107 inline bool wait(int timeout) 00108 { 00109 bool temp; 00110 temp = m_pSemaphore->tryAcquire(m_numOfListeners, timeout); 00111 00112 QMutexLocker mutexLocker(&internalMutex); 00113 if(temp == false) 00114 { 00115 qDebug() << "ItomSharedSemaphore run into a timeout. Number of attempted listeners: " << m_numOfListeners << ", already freed: " << m_pSemaphore->available(); 00116 } 00117 else 00118 { 00119 m_pSemaphore->release(m_numOfListeners); 00120 } 00121 00122 m_callerStillWaiting = false; 00123 00124 return temp; 00125 } 00126 00127 bool waitAndProcessEvents(int timeout, QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); 00128 00130 /* 00131 the called method in another thread must release the semaphore as soon as possible such that the caller can continue 00132 */ 00133 inline void release() { /*qDebug() << "semaphore release";*/ m_pSemaphore->release(1); } 00134 00136 /* 00137 @return true if semaphore is still locked, else false 00138 */ 00139 inline int available() const { return m_pSemaphore->available(); } 00140 00142 /* 00143 this method is not 100% thread-safe, that means it might occure, that the wait-method of the caller drops into the timeout 00144 during the call to the method isCallerStillWaiting. Therefore consider this method as pure information. 00145 00146 @return true if caller-method is still waiting (in \sa wait-method) that all listeners are calling the release method 00147 in order to free the lock of the semaphore. else: false 00148 */ 00149 inline bool isCallerStillWaiting() { QMutexLocker mutexLocker(&internalMutex); return m_callerStillWaiting; } 00150 00152 // 00153 // Every listener and the caller-method must call this static method with the pointer to the corresponding ItomSharedSemaphore 00154 // in order to guarantee the final deletion of the semaphore, if it is not needed any more by any participating method (caller or listener). 00155 // 00156 // In every listener method (called method) you should call this method after you released the semaphore (\sa release). 00157 // The ItomSharedSemaphore consists of a internal reference counter, which is set to the number of listeners plus 1 at 00158 // construction time. Every call to deleteSemaphore decreases this counter and if this counter drops to zero, no method 00159 // uses the semaphore any more such that it is safely deleted. Be careful that you don't access the semaphore in a method 00160 // where you already called deleteSemaphore with the semaphore-pointer as parameter. 00161 // 00162 // In order to simplify the handling of ItomSharedSemaphore consider to used ItomSharedSemaphoreLocker. 00163 00164 inline void deleteSemaphore(void) 00165 { 00166 QMutexLocker mutexLocker(&internalMutex); 00167 00168 m_instCounter --; 00169 if(m_instCounter <= 0) 00170 { 00171 m_enableDelete = true; 00172 mutexLocker.unlock(); 00173 delete this; 00174 return; 00175 } 00176 00177 return; 00178 } 00179 00180 ito::RetVal returnValue; 00181 }; 00182 00183 00191 class ItomSharedSemaphoreLocker 00192 { 00193 public: 00195 inline ItomSharedSemaphoreLocker(ItomSharedSemaphore* semaphore) : m_semaphore(semaphore) {} 00196 00198 inline ItomSharedSemaphoreLocker() : m_semaphore(NULL) {} 00199 00201 inline ~ItomSharedSemaphoreLocker() 00202 { 00203 if(m_semaphore) 00204 { 00205 m_semaphore->deleteSemaphore(); 00206 m_semaphore = NULL; 00207 } 00208 } 00209 00211 inline ItomSharedSemaphore* getSemaphore() const { return m_semaphore; } 00212 00214 ItomSharedSemaphore* operator ->() const { return m_semaphore; } 00215 00217 /* 00218 If this locker already guards an instance of ItomSharedSemaphore its reference counter is decremented first. \sa ItomSharedSemaphore::deleteSemaphore. 00219 */ 00220 inline ItomSharedSemaphoreLocker & operator = (ItomSharedSemaphore *newSemaphoreInstance) 00221 { 00222 if(m_semaphore) 00223 { 00224 m_semaphore->deleteSemaphore(); 00225 m_semaphore = NULL; 00226 } 00227 m_semaphore = newSemaphoreInstance; 00228 return *this; 00229 } 00230 00231 private: 00232 inline ItomSharedSemaphoreLocker(ItomSharedSemaphoreLocker & /*other*/ ) { /* forbidden */ } 00233 inline ItomSharedSemaphoreLocker & operator = (const ItomSharedSemaphoreLocker & /*other*/ ) { return *this; /* forbidden */ } 00234 ItomSharedSemaphore* m_semaphore; 00235 }; 00236 00237 //} //end namespace ito 00238 00239 #endif //#if !defined(Q_MOC_RUN) || defined(ITOMCOMMONQT_MOC) 00240 00241 #endif