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