00001
00008
00009
00010
00011
00012 #ifndef ECL_THREADS_MUTEX_POS_HPP_
00013 #define ECL_THREADS_MUTEX_POS_HPP_
00014
00015
00016
00017
00018
00019 #include <ecl/config/ecl.hpp>
00020 #if defined(ECL_IS_POSIX)
00021
00022
00023
00024
00025
00026 #include <errno.h>
00027 #include <cstring>
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
00039
00040
00041 namespace ecl {
00042
00043
00044
00045
00046
00047 typedef pthread_mutex_t RawMutex;
00049
00050
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 };
00163
00164
00165
00166
00167
00168 #if defined(ECL_HAS_EXCEPTIONS)
00169 namespace ecl {
00170 namespace threads {
00171
00172
00173
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
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
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 };
00288 }
00289
00290 #endif
00291 #endif
00292 #endif