$search
00001 00008 /***************************************************************************** 00009 ** Ifdefs 00010 *****************************************************************************/ 00011 00012 #ifndef ECL_THREADS_MUTEX_POS_HPP_ 00013 #define ECL_THREADS_MUTEX_POS_HPP_ 00014 00015 /***************************************************************************** 00016 ** Platform Check 00017 *****************************************************************************/ 00018 00019 #include <ecl/config/ecl.hpp> 00020 #if defined(ECL_IS_POSIX) 00021 00022 /***************************************************************************** 00023 ** Includes 00024 *****************************************************************************/ 00025 00026 #include <errno.h> 00027 #include <cstring> // strerror function 00028 #include <string> 00029 #include <pthread.h> 00030 #include <sstream> 00031 #include <ecl/config/macros.hpp> 00032 #include <ecl/exceptions/macros.hpp> 00033 #include <ecl/exceptions/standard_exception.hpp> 00034 #include <ecl/time/duration.hpp> 00035 00036 00037 /***************************************************************************** 00038 ** Namespaces 00039 *****************************************************************************/ 00040 00041 namespace ecl { 00042 00043 /***************************************************************************** 00044 ** Typedefs 00045 *****************************************************************************/ 00046 00047 typedef pthread_mutex_t RawMutex; 00049 /***************************************************************************** 00050 ** Class Mutex 00051 *****************************************************************************/ 00080 class Mutex { 00081 public: 00092 Mutex(const bool locked = false) ecl_assert_throw_decl(StandardException); 00098 virtual ~Mutex(); 00099 00105 void unlock() ecl_assert_throw_decl(StandardException); 00111 void lock() ecl_assert_throw_decl(StandardException); 00125 bool trylock(Duration &duration) ecl_assert_throw_decl(StandardException); 00136 bool trylock() ecl_assert_throw_decl(StandardException); 00146 unsigned int locks() { return number_locks; } 00147 00154 RawMutex& rawType() { return mutex; } 00155 00156 private: 00157 RawMutex mutex; 00158 unsigned int number_locks; 00159 00160 }; 00161 00162 }; // namespace ecl 00163 00164 /***************************************************************************** 00165 ** Interface [Exceptions] 00166 *****************************************************************************/ 00167 00168 #if defined(ECL_HAS_EXCEPTIONS) 00169 namespace ecl { 00170 namespace threads { 00171 00172 /***************************************************************************** 00173 ** Interface [Mutex Exceptions] 00174 *****************************************************************************/ 00175 00184 inline StandardException ECL_LOCAL throwMutexAttrException(const char* loc, int error_result) { 00185 switch (error_result) { 00186 case ( EINVAL ) : return StandardException(loc, InvalidInputError, "The specified mutex attribute was invalid."); 00187 case ( ENOMEM ) : return StandardException(loc, MemoryError, "There is insufficient memory for initialisation of the mutex attribute."); 00188 default : 00189 { 00190 std::ostringstream ostream; 00191 ostream << "Unknown posix error " << error_result << ": " << strerror(error_result) << "."; 00192 return StandardException(loc, UnknownError, ostream.str()); 00193 } 00194 } 00195 } 00204 inline StandardException ECL_LOCAL throwMutexInitException(const char* loc, int error_result) { 00205 switch (error_result) { 00206 case ( EINVAL ) : return StandardException(loc, InvalidInputError, "The specified mutex was invalid."); 00207 case ( EBUSY ) : return StandardException(loc, InvalidInputError, "The mutex object has already been initialised and not yet destroyed."); 00208 case ( EAGAIN ) : return StandardException(loc, MemoryError, "The mutex object has already been initialised and not yet destroyed."); 00209 case ( ENOMEM ) : return StandardException(loc, MemoryError, "There is insufficient memory for initialisation of the mutex."); 00210 case ( EPERM ) : return StandardException(loc, PermissionsError, "The user does not have the privilege to perform the operation."); 00211 default : 00212 { 00213 std::ostringstream ostream; 00214 ostream << "Unknown posix error " << error_result << ": " << strerror(error_result) << "."; 00215 return StandardException(loc, UnknownError, ostream.str()); 00216 } 00217 } 00218 } 00227 inline StandardException ECL_LOCAL throwMutexDestroyException(const char* loc, int error_result) { 00228 switch (error_result) { 00229 case ( EINVAL ) : return StandardException(loc, DestructorError, "The specified mutex is invalid (for some reason or other)."); 00230 case ( EBUSY ) : return StandardException(loc, DestructorError, "Attempted to destroy the mutex while it was locked."); 00231 default : return StandardException(loc, UnknownError, "Unknown error."); 00232 } 00233 } 00242 inline StandardException ECL_LOCAL throwMutexTimedLockException(const char* loc, int error_result) { 00243 switch (error_result) { 00244 case ( EDEADLK ): return StandardException(loc, UsageError, "DEADLOCK! The current thread already owns the mutex."); 00245 // These aren't relevant to us (EBUSY is normal operation for trylock, EINVAL can't happen because of RAII, and EAGAIN because our mutex isn't RECURSIVE) 00246 case ( EINVAL ) : return StandardException(loc, UsageError, "The mutex is not initialised or it is priority protected and the calling thread's priority is higher than the mutex' current priority ceiling."); 00247 case ( EAGAIN ) : return StandardException(loc, OutOfRangeError, "The mutex could not be acquired because the maximum number of recursive locks for the mutex has been exceeded."); 00248 default : return StandardException(loc, UnknownError, "Unknown error."); 00249 } 00250 } 00259 inline StandardException ECL_LOCAL throwMutexLockException(const char* loc, int error_result) { 00260 switch (error_result) { 00261 case ( EDEADLK ): return StandardException(loc, UsageError, "DEADLOCK! The mutex has already been locked by this thread, it now has to wait on itself."); 00262 // These aren't relevant to us (EBUSY is normal operation for trylock, EINVAL can't happen because of RAII, and EAGAIN because our mutex isn't RECURSIVE) 00263 case ( EBUSY ) : return StandardException(loc, ConfigurationError, "The try lock failed because it was already locked (normal operation really, not really an error)."); 00264 case ( EINVAL ) : return StandardException(loc, InvalidInputError, "The mutex does not refer to an initialised mutex."); 00265 case ( EAGAIN ) : return StandardException(loc, OutOfRangeError, "The mutex could not be acquired because the maximum number of recursive locks for the mutex has been exceeded."); 00266 default : return StandardException(loc, PosixError, "Unknown error."); 00267 } 00268 } 00277 inline StandardException ECL_LOCAL throwMutexUnLockException(const char* loc, int error_result) { 00278 switch (error_result) { 00279 case ( EINVAL ) : return StandardException(loc, InvalidInputError, "The mutex does not refer to an initialised mutex."); 00280 case ( EAGAIN ) : return StandardException(loc, OutOfRangeError, "The mutex could not be acquired because the maximum number of recursive locks for the mutex has been exceeded."); 00281 case ( EPERM ) : return StandardException(loc, PermissionsError, "The user does not have the privilege to perform the operation."); 00282 default : return StandardException(loc, UnknownError, "Unknown error."); 00283 } 00284 } 00285 00286 00287 }; // namespace threads 00288 } // namespace ecl 00289 00290 #endif /* ECL_HAS_EXCEPTIONS */ 00291 #endif /* ECL_IS_POSIX */ 00292 #endif /* ECL_THREADS_MUTEX_POS_HPP_ */