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