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