itom 1.0.14
D:/git-itom/sources/itom/DataObject/readWriteLock.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 READWRITELOCK
00029 #define READWRITELOCK
00030 
00031 // Use Window or Posix
00032 //#if defined (_WINDOWS) || defined (WIN32)
00033 #ifdef WIN32
00034      #include <windows.h>
00035 #else
00036      #ifndef POSIX
00037 //          #warning POSIX will be used (but you did not define it)
00038      #endif
00039      #include <pthread.h>
00040 #endif
00041 
00050 #ifdef WIN32
00051 //#if defined _WINDOWS || defined WIN32
00052 
00053     class ReadWriteLock
00054     {
00055     private:
00056 
00057         ReadWriteLock(const ReadWriteLock &) {}
00058 
00059         int nrOfReaders;                
00060         int status;                     
00061         bool writeGelocked;
00062         CRITICAL_SECTION mAtomicOp;     
00063         CRITICAL_SECTION mReadLock;     
00064         CRITICAL_SECTION mWriteLock;    
00065 
00066     public:
00068 
00071         ReadWriteLock(int lockStatus = 0) : nrOfReaders(0), status(0), writeGelocked(false)
00072         {
00073             InitializeCriticalSection(&mAtomicOp);
00074             InitializeCriticalSection(&mReadLock);
00075             InitializeCriticalSection(&mWriteLock);
00076 
00077             if(lockStatus == -1)
00078             {
00079                 lockWrite();
00080                 status = -1;
00081             }
00082             else if(lockStatus > 0)
00083             {
00084                 lockRead(lockStatus);
00085                 status = lockStatus;
00086             }
00087         };
00088 
00090 
00092         ~ReadWriteLock()
00093         {
00094             TryEnterCriticalSection(&mAtomicOp);
00095             LeaveCriticalSection(&mAtomicOp);
00096             DeleteCriticalSection(&mAtomicOp);
00097             TryEnterCriticalSection(&mReadLock);
00098             LeaveCriticalSection(&mReadLock);
00099             DeleteCriticalSection(&mReadLock);
00100             TryEnterCriticalSection(&mWriteLock);
00101             LeaveCriticalSection(&mWriteLock);
00102             DeleteCriticalSection(&mWriteLock);
00103         };
00104 
00106 
00112         void lockRead(int increment = 1)
00113         {
00114             //if(!TryEnterCriticalSection(&mWriteLock))
00115             //{
00116             //    int i=1;
00117             //    EnterCriticalSection(&mWriteLock);
00118             //    std::cout << "try failed2" << std::endl;
00119             //}
00120             EnterCriticalSection(&mWriteLock);
00121 
00122             writeGelocked = true;
00123             EnterCriticalSection(&mAtomicOp);
00124             TryEnterCriticalSection(&mReadLock);
00125             nrOfReaders+= increment;
00126             status = nrOfReaders;
00127             LeaveCriticalSection(&mAtomicOp);
00128             LeaveCriticalSection(&mWriteLock);
00129             writeGelocked = false;
00130         }
00131 
00133 
00137         void lockWrite()
00138         {
00139             //if(!TryEnterCriticalSection(&mWriteLock))
00140             //{
00141             //    int i=1;
00142             //    EnterCriticalSection(&mWriteLock);
00143             //    std::cout << "try failed" << std::endl;
00144             //}
00145             EnterCriticalSection(&mWriteLock);
00146 
00147             writeGelocked = true;
00148             EnterCriticalSection(&mReadLock);
00149             EnterCriticalSection(&mAtomicOp);
00150             status = -1;
00151             LeaveCriticalSection(&mAtomicOp);
00152         }
00153 
00155 
00159         void unlock()
00160         {
00161             EnterCriticalSection(&mAtomicOp);
00162             if(nrOfReaders == 0)
00163             {
00164                 while(mReadLock.RecursionCount > 0) LeaveCriticalSection(&mReadLock);
00165                 while(mWriteLock.RecursionCount > 0) LeaveCriticalSection(&mWriteLock);
00166                 writeGelocked = false;
00167                 status = 0;
00168             }
00169             else
00170             {
00171                 if(nrOfReaders > 0)  nrOfReaders--;
00172                 status = nrOfReaders;
00173                 if(nrOfReaders <= 0)
00174                 {
00175                     while(mReadLock.RecursionCount > 0) LeaveCriticalSection(&mReadLock);
00176                 }
00177             }
00178             LeaveCriticalSection(&mAtomicOp);
00179         }
00180 
00182 
00185         void _unlock(int value)
00186         {
00187             EnterCriticalSection(&mAtomicOp);
00188             if(value == -1)
00189             {
00190                 TryEnterCriticalSection(&mReadLock);
00191                 while(mReadLock.RecursionCount > 0) LeaveCriticalSection(&mReadLock);
00192                 TryEnterCriticalSection(&mWriteLock);
00193                 while(mWriteLock.RecursionCount > 0) LeaveCriticalSection(&mWriteLock);
00194                 writeGelocked = false;
00195                 status = 0;
00196             }
00197             else
00198             {
00199                 nrOfReaders -= value;
00200                 if(nrOfReaders <= 0)
00201                 {
00202                     nrOfReaders = 0;
00203                     TryEnterCriticalSection(&mReadLock);
00204                     while(mReadLock.RecursionCount > 0) LeaveCriticalSection(&mReadLock);
00205                 }
00206                 status = nrOfReaders;
00207             }
00208             LeaveCriticalSection(&mAtomicOp);
00209         }
00210 
00212 
00215         inline int getLockStatus() const { return status; }
00216     };
00217 
00218 #else
00219 
00220     class ReadWriteLock
00221     {
00222         public:
00224 
00228             ReadWriteLock(int lockStatus = 0) : nrOfReaders(0), status(0), writeGelocked(false)
00229             {
00230                 pthread_mutexattr_t attr;
00231                 pthread_mutexattr_init(&attr);
00232                 pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
00233                 pthread_mutex_init(&mAtomicOp,&attr);
00234                 pthread_mutex_init(&mReadLock,&attr);
00235                 pthread_mutex_init(&mWriteLock,&attr);
00236                 pthread_mutexattr_destroy(&attr);
00237 
00238                 if(lockStatus == -1)
00239                 {
00240                     lockWrite();
00241                     status = -1;
00242                 }
00243                 else if(lockStatus > 0)
00244                 {
00245                     lockRead(lockStatus);
00246                     status = lockStatus;
00247                 }
00248             }
00249 
00251 
00253             ~ReadWriteLock()
00254             {
00255                 pthread_mutex_trylock(&mAtomicOp);
00256                 pthread_mutex_unlock(&mAtomicOp);
00257                 pthread_mutex_destroy(&mAtomicOp);
00258                 pthread_mutex_trylock(&mReadLock);
00259                 pthread_mutex_unlock(&mReadLock);
00260                 pthread_mutex_destroy(&mReadLock);
00261                 pthread_mutex_trylock(&mWriteLock);
00262                 pthread_mutex_unlock(&mWriteLock);
00263                 pthread_mutex_destroy(&mWriteLock);
00264             }
00265 
00267 
00273             void lockRead(int increment = 1)
00274             {
00275                 pthread_mutex_lock(&mWriteLock);
00276                 pthread_mutex_lock(&mAtomicOp);
00277                 pthread_mutex_trylock(&mReadLock);
00278                 nrOfReaders+=increment;
00279                 status = nrOfReaders;
00280                 pthread_mutex_unlock(&mAtomicOp);
00281                 pthread_mutex_unlock(&mWriteLock);
00282             }
00283 
00285 
00289             void lockWrite()
00290             {
00291                 pthread_mutex_lock(&mWriteLock);
00292                 pthread_mutex_lock(&mReadLock);
00293                 pthread_mutex_lock(&mAtomicOp);
00294                 status = -1;
00295                 pthread_mutex_unlock(&mAtomicOp);
00296             }
00297 
00299 
00303             void unlock()
00304             {
00305                 pthread_mutex_lock(&mAtomicOp);
00306                 if(nrOfReaders == 0)
00307                 {
00308                     pthread_mutex_unlock(&mReadLock);
00309                     pthread_mutex_unlock(&mWriteLock);
00310                     status = 0;
00311                 }
00312                 else
00313                 {
00314                     if(nrOfReaders > 0)  nrOfReaders--;
00315                     status = nrOfReaders;
00316                     if(nrOfReaders <= 0) pthread_mutex_unlock(&mReadLock);
00317                 }
00318                 pthread_mutex_unlock(&mAtomicOp);
00319             }
00320 
00322 
00325             void _unlock(int value)
00326             {
00327                 pthread_mutex_lock(&mAtomicOp);
00328                 if(value == -1)
00329                 {
00330                     pthread_mutex_trylock(&mReadLock);
00331                     pthread_mutex_unlock(&mReadLock);
00332                     pthread_mutex_trylock(&mWriteLock);
00333                     pthread_mutex_unlock(&mWriteLock);
00334                     status = 0;
00335                 }
00336                 else
00337                 {
00338                     nrOfReaders -= value;
00339                     if(nrOfReaders <= 0)
00340                     {
00341                         nrOfReaders = 0;
00342                         pthread_mutex_trylock(&mReadLock);
00343                         pthread_mutex_unlock(&mReadLock);
00344                     }
00345                     status = nrOfReaders;
00346                 }
00347                 pthread_mutex_unlock(&mAtomicOp);
00348             }
00349 
00351 
00354             inline int getLockStatus() const { return status; }
00355 
00356         private:
00357 
00358             ReadWriteLock(const ReadWriteLock &) {}
00359 
00360             int nrOfReaders;                
00361             int status;                     
00362             bool writeGelocked;
00363             pthread_mutex_t mAtomicOp;     
00364             pthread_mutex_t mReadLock;     
00365             pthread_mutex_t mWriteLock;    
00366     };
00367 
00368 #endif
00369 
00370 
00371 
00372 #endif
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends