00001 /*************************************************************************** 00002 LOW_thread_mutex.h - description 00003 ------------------- 00004 begin : Fri Oct 3 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_MUTEX_H 00019 #define LOW_THREAD_MUTEX_H 00020 00021 00022 #include "LOW_exception.h" 00023 00024 00025 /** Abstract base class for thread mutex. 00026 Each instance represents one thread mutex. 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 Implementation classes must at least support three kinds od a mutex as 00034 defined by mutexKind_t. 00035 00036 This class is thread-safe. 00037 00038 @see LOW_thread_Factory 00039 00040 @author Harald Roelle 00041 @author Parts of the documentation taken from Linux man pages by Xavier Leroy. 00042 */ 00043 class LOW_thread_mutex { 00044 00045 //======================================================================================= 00046 public: 00047 00048 //===================================================================================== 00049 // 00050 // exceptions 00051 // 00052 00053 /** Exception base class for all exceptions thrown by LOW_thread_mutex. */ 00054 class_DERIVE_FROM_EXCEPTION( thread_mutex_error, LOW_exception); 00055 00056 /** Exception class to indicate a mutex already locked by the calling thread. */ 00057 class_DERIVE_FROM_EXCEPTION( thread_mutex_locked, thread_mutex_error); 00058 00059 /** Exception class to indicate a mutex locked by another thread. */ 00060 class_DERIVE_FROM_EXCEPTION( thread_mutex_busy, thread_mutex_error); 00061 00062 00063 //===================================================================================== 00064 // 00065 // locks 00066 // 00067 00068 /** Locking class for a mutex. 00069 00070 The class is intended to be used in a "locking is creation" design pattern. 00071 On creation a lock is optained on the mutex, and on destruction the mutex is released. 00072 */ 00073 class mutexLock { 00074 public: 00075 /** Obtain the lock. 00076 Inlined for performance reasons. 00077 @param inMutex Pointer to the mutex the lock is for. 00078 */ 00079 inline mutexLock( LOW_thread_mutex &inMutex) : 00080 mutex( inMutex) 00081 { 00082 mutex.lock(); 00083 }; 00084 00085 /** Release the lock. 00086 Inlined for performance reasons. 00087 */ 00088 inline ~mutexLock() 00089 { 00090 mutex.unlock(); 00091 }; 00092 00093 private: 00094 LOW_thread_mutex &mutex; /**< Pointer to the mutex the lock is for. */ 00095 }; 00096 00097 00098 //===================================================================================== 00099 // 00100 // type definitions 00101 // 00102 00103 /** Basic type of a mutex. */ 00104 typedef enum { 00105 mutexKind_fast = 0, /**< Binary mutex without deadlock prevention when called locked twice by same thread. */ 00106 mutexKind_recursive, /**< Integer/counting mutex. */ 00107 mutexKind_errorCheck /**< Binary mutex with deadlock prevention and extended error checking. */ 00108 } mutexKind_t; 00109 00110 00111 00112 //===================================================================================== 00113 // 00114 // constructor 00115 // 00116 00117 /** Constructor. 00118 @param inMutexKind Kind of the new mutex. 00119 @throw thread_mutex_error Any error. 00120 */ 00121 LOW_thread_mutex( const mutexKind_t inMutexKind); 00122 00123 00124 /** Destructor. 00125 @throw thread_mutex_busy The mutex is still locked. 00126 @throw thread_mutex_error Any other error. 00127 */ 00128 virtual ~LOW_thread_mutex(); 00129 00130 00131 //===================================================================================== 00132 // 00133 // methods 00134 // 00135 00136 /** Get kind of the mutex. 00137 @return Kind of the mutex. 00138 */ 00139 virtual mutexKind_t getKind() const; 00140 00141 00142 /** Obtain a lock on the mutex (blocking). 00143 00144 Blocks the calling thread if another thread has already locked the mutex. 00145 00146 If the mutex is already locked by the calling thread, behaviour depends on the mutex kind: 00147 00148 - <B>mutexKind_fast:</B> The calling thread is suspended until the mutex is unlocked, 00149 thus effectively causing the calling thread to deadlock. 00150 - <B>mutexKind_recursive:</B> The call succeeds and returns immediately, recording 00151 the number of times the calling thread has locked the mutex. An equal number of 00152 unlock() calls must be performed before the mutex returns to the unlocked state. 00153 - <B>mutexKind_errorCheck:</B> A thread_mutex_locked exception is thrown. 00154 00155 Abstract method to be implemented by derived class. 00156 00157 @throw thread_mutex_locked Calling thread has already locked the mutex and 00158 mutex kind is mutexKind_errorCheck. 00159 @throw thread_mutex_error Any other error. 00160 */ 00161 virtual void lock() = 0; 00162 00163 00164 /** Obtain a lock on the mutex (non-blocking). 00165 00166 Behaves identically to lock(), except that it does not block the calling thread 00167 if the mutex is already locked by another thread. 00168 Instead an thread_mutex_busy exception is thrown. 00169 00170 Abstract method to be implemented by derived class. 00171 00172 @throw thread_mutex_busy The mutex is already locked by another thread. 00173 @throw thread_mutex_locked Calling thread has already locked the mutex and 00174 mutex kind is mutexKind_errorCheck. 00175 @throw thread_mutex_error Any other error. 00176 */ 00177 virtual void tryLock() = 0; 00178 00179 00180 /** Release a lock on the mutex. 00181 Behaviour depends on the mutex kind: 00182 00183 - <B>mutexKind_fast:</B> The mutex is assumed to be locked and owned by the calling 00184 thread on entrance and always returns it to the unlocked state. 00185 - <B>mutexKind_recursive:</B> The mutex is assumed to be locked and owned by the calling 00186 thread on entrance. Decrements the locking count of the mutex (number of 00187 lock() calls performed on it by the calling thread), and only when this count reaches 00188 zero is the mutex actually unlocked. 00189 - <B>mutexKind_errorCheck:</B> Actually checks at run-time that the mutex is locked on 00190 entrance, and that it was locked by the same thread that is now calling. 00191 00192 Abstract method to be implemented by derived class. 00193 00194 @throw thread_mutex_busy The mutex is already by another thread. 00195 @throw thread_mutex_error Any other error. 00196 */ 00197 virtual void unlock() = 0; 00198 00199 00200 //======================================================================================= 00201 private: 00202 00203 //===================================================================================== 00204 // 00205 // attributes 00206 // 00207 00208 const mutexKind_t mutexKind; 00209 }; 00210 00211 #endif