00001 /*************************************************************************** 00002 LOW_thread_rwlock.h - description 00003 ------------------- 00004 begin : Sun Oct 5 2003 00005 copyright : (C) 2003 by Harald Roelle 00006 email : roelle@informatik.uni-muenchen.de 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #ifndef LOW_THREAD_RWLOCK_H 00019 #define LOW_THREAD_RWLOCK_H 00020 00021 00022 #include "LOW_exception.h" 00023 00024 00025 /** Abstract base class for read-write locks. 00026 Each instance represents one lock. 00027 00028 Specific platforms dereive their implementation classes from this class. 00029 00030 The instances are created by LOW_thread_Factory, following the factory 00031 design pattern. 00032 00033 This class is thread-safe. 00034 00035 @see LOW_thread_Factory 00036 00037 @author Harald Roelle 00038 @author Parts of the documentation taken from Linux man pages by Xavier Leroy. 00039 @author Parts of the documentation taken from IEEE Standard 1003.1-2003. 00040 */ 00041 class LOW_thread_rwlock { 00042 00043 //======================================================================================= 00044 public: 00045 00046 //===================================================================================== 00047 // 00048 // exceptions 00049 // 00050 00051 /** Exception base class for all exceptions thrown by LOW_thread_rwlock. */ 00052 class_DERIVE_FROM_EXCEPTION( thread_rwlock_error, LOW_exception); 00053 00054 /** Exception class to indicate a mutex already locked by the calling thread. */ 00055 class_DERIVE_FROM_EXCEPTION( thread_rwlock_locked, thread_rwlock_error); 00056 00057 /** Exception class to indicate a mutex locked by another thread. */ 00058 class_DERIVE_FROM_EXCEPTION( thread_rwlock_busy, thread_rwlock_error); 00059 00060 00061 //===================================================================================== 00062 // 00063 // locks 00064 // 00065 00066 /** Read locking class for a rwlock. 00067 00068 The class is intended to be used in a "locking is creation" design pattern. 00069 On creation a read lock is optained on the rwlock, and on destruction the rwlock is released. 00070 */ 00071 class rwLockRead { 00072 public: 00073 /** Obtain the read lock. 00074 Inlined for performance reasons. 00075 @param inRwlock Reference to the rwlock the lock is for. 00076 */ 00077 inline rwLockRead( LOW_thread_rwlock &inRwlock) : 00078 rwlock( inRwlock) 00079 { 00080 rwlock.lockRead(); 00081 }; 00082 00083 /** Release the read lock. 00084 Inlined for performance reasons. 00085 */ 00086 inline ~rwLockRead() 00087 { 00088 rwlock.unlock(); 00089 }; 00090 00091 private: 00092 LOW_thread_rwlock &rwlock; /**< Reference to the rwlock the lock is for. */ 00093 }; 00094 00095 00096 /** Write locking class for a rwlock. 00097 00098 The class is intended to be used in a "locking is creation" design pattern. 00099 On creation a write lock is optained on the rwlock, and on destruction the rwlock is released. 00100 */ 00101 class rwLockWrite { 00102 public: 00103 /** Obtain the write lock. 00104 Inlined for performance reasons. 00105 @param inRwlock Reference to the mutex the lock is for. 00106 */ 00107 inline rwLockWrite( LOW_thread_rwlock &inRwlock) : 00108 rwlock( inRwlock) 00109 { 00110 rwlock.lockWrite(); 00111 }; 00112 00113 /** Release the read lock. 00114 Inlined for performance reasons. 00115 */ 00116 inline ~rwLockWrite() 00117 { 00118 rwlock.unlock(); 00119 }; 00120 00121 private: 00122 LOW_thread_rwlock &rwlock; /**< Reference to the rwlock the lock is for. */ 00123 }; 00124 00125 00126 //===================================================================================== 00127 // 00128 // constructors 00129 // 00130 00131 /** Destructor. 00132 @throw thread_rwlock_busy The lock is still locked. 00133 @throw thread_rwlock_error Any other error. 00134 */ 00135 virtual ~LOW_thread_rwlock(); 00136 00137 00138 //===================================================================================== 00139 // 00140 // methods 00141 // 00142 00143 /** Obtain a read lock on the rwlock (blocking). 00144 00145 The method applies a read lock to the read-write lock. 00146 The calling thread acquires the read lock if a writer does not hold the lock and 00147 there are no writers blocked on the lock. 00148 00149 A thread may hold multiple concurrent read locks on rwlock (that is, successfully 00150 call the lockRead() method n times). If so, the application shall ensure that the 00151 thread performs matching unlocks (that is, it calls unlock() method n times). 00152 00153 @throw thread_rwlock_locked Calling thread already owns rwlock for writing. 00154 @throw thread_rwlock_error Any other error. 00155 */ 00156 virtual void lockRead() = 0; 00157 00158 00159 /** Obtain a read lock on the rwlock (non-blocking). 00160 00161 The method applies a read lock as in the lockRead() method, with the exception 00162 that the function throws an exception if the equivalent lockRead() call would 00163 have blocked the calling thread. The method never blocks; it always either 00164 acquires the lock or throws a thread_rwlock_busy exception. 00165 00166 @throw thread_rwlock_busy The rwlock is already locked for writing by another thread. 00167 @throw thread_rwlock_locked Calling thread already owns rwlock for writing. 00168 @throw thread_rwlock_error Any other error. 00169 */ 00170 virtual void tryLockRead() = 0; 00171 00172 00173 /** Obtain a write lock on the rwlock (blocking). 00174 00175 The method applies a write lock to the read-write lock. 00176 The calling thread acquires the write lock if no other thread (reader or writer) 00177 holds the read-write lock rwlock. Otherwise, the thread will block until it can 00178 acquire the lock. The calling thread may deadlock if at the time the call is made 00179 it holds the read-write lock (whether a read or write lock). 00180 00181 @throw thread_rwlock_locked Calling thread already owns the read-write lock for writing or reading. 00182 @throw thread_rwlock_error Any other error. 00183 */ 00184 virtual void lockWrite() = 0; 00185 00186 00187 /** Obtain a write lock on the rwlock (non-blocking). 00188 00189 The method applies a write lock like the lockWrite() method, with the exception 00190 that the function throws an exception if any thread currently holds the 00191 rwlock (for reading or writing). 00192 00193 @throw thread_rwlock_busy The rwlock is already locked for reading or writing. 00194 @throw thread_rwlock_locked Calling thread already owns the read-write lock for writing or reading. 00195 @throw thread_rwlock_error Any other error. 00196 */ 00197 virtual void tryLockWrite() = 0; 00198 00199 00200 /** Release a lock on the rwlock. 00201 00202 The method releasees a lock held on the read-write lock. Results are undefined if the read-write 00203 lock rwlock is not held by the calling thread. 00204 00205 If this method is called to release a read lock from the read-write lock object and 00206 there are other read locks currently held on this read-write lock object, the read-write 00207 lock object remains in the read locked state. If this method releases the last read lock 00208 for this read-write lock object, the read-write lock object is put in the unlocked 00209 state with no owners. 00210 00211 If this method is called to release a write lock for this read-write lock object, 00212 the read-write lock object is put in the unlocked state. 00213 00214 @throw thread_rwlock_busy calling thread does not hold a lock. 00215 @throw thread_rwlock_error Any other error. 00216 */ 00217 virtual void unlock() = 0; 00218 }; 00219 00220 #endif