itom 1.0.14
|
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