itom 1.3.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 
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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends