itom 2.0.0
D:/git-itom/sources/itom/common/sharedStructuresQt.h
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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends