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