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