Program Listing for File mutex_pos.hpp
↰ Return to documentation for file (include/ecl/threads/mutex_pos.hpp
)
/*****************************************************************************
** Ifdefs
*****************************************************************************/
#ifndef ECL_THREADS_MUTEX_POS_HPP_
#define ECL_THREADS_MUTEX_POS_HPP_
/*****************************************************************************
** Platform Check
*****************************************************************************/
#include <ecl/config/ecl.hpp>
#if defined(ECL_IS_POSIX)
/*****************************************************************************
** Includes
*****************************************************************************/
#include <errno.h>
#include <cstring> // strerror function
#include <string>
#include <pthread.h>
#include <sstream>
#include <ecl/config/macros.hpp>
#include <ecl/exceptions/macros.hpp>
#include <ecl/exceptions/standard_exception.hpp>
#include <ecl/time/duration.hpp>
/*****************************************************************************
** Namespaces
*****************************************************************************/
namespace ecl {
/*****************************************************************************
** Typedefs
*****************************************************************************/
typedef pthread_mutex_t RawMutex;
/*****************************************************************************
** Class Mutex
*****************************************************************************/
class Mutex {
public:
Mutex(const bool locked = false);
virtual ~Mutex();
void unlock();
void lock();
bool trylock(Duration &duration);
bool trylock();
unsigned int locks() { return number_locks; }
RawMutex& rawType() { return mutex; }
private:
RawMutex mutex;
unsigned int number_locks;
};
} // namespace ecl
/*****************************************************************************
** Interface [Exceptions]
*****************************************************************************/
#if defined(ECL_HAS_EXCEPTIONS)
namespace ecl {
namespace threads {
/*****************************************************************************
** Interface [Mutex Exceptions]
*****************************************************************************/
inline StandardException ECL_LOCAL throwMutexAttrException(const char* loc, int error_result) {
switch (error_result) {
case ( EINVAL ) : return StandardException(loc, InvalidInputError, "The specified mutex attribute was invalid.");
case ( ENOMEM ) : return StandardException(loc, MemoryError, "There is insufficient memory for initialisation of the mutex attribute.");
default :
{
std::ostringstream ostream;
ostream << "Unknown posix error " << error_result << ": " << strerror(error_result) << ".";
return StandardException(loc, UnknownError, ostream.str());
}
}
}
inline StandardException ECL_LOCAL throwMutexInitException(const char* loc, int error_result) {
switch (error_result) {
case ( EINVAL ) : return StandardException(loc, InvalidInputError, "The specified mutex was invalid.");
case ( EBUSY ) : return StandardException(loc, InvalidInputError, "The mutex object has already been initialised and not yet destroyed.");
case ( EAGAIN ) : return StandardException(loc, MemoryError, "The mutex object has already been initialised and not yet destroyed.");
case ( ENOMEM ) : return StandardException(loc, MemoryError, "There is insufficient memory for initialisation of the mutex.");
case ( EPERM ) : return StandardException(loc, PermissionsError, "The user does not have the privilege to perform the operation.");
default :
{
std::ostringstream ostream;
ostream << "Unknown posix error " << error_result << ": " << strerror(error_result) << ".";
return StandardException(loc, UnknownError, ostream.str());
}
}
}
inline StandardException ECL_LOCAL throwMutexDestroyException(const char* loc, int error_result) {
switch (error_result) {
case ( EINVAL ) : return StandardException(loc, DestructorError, "The specified mutex is invalid (for some reason or other).");
case ( EBUSY ) : return StandardException(loc, DestructorError, "Attempted to destroy the mutex while it was locked.");
default : return StandardException(loc, UnknownError, "Unknown error.");
}
}
inline StandardException ECL_LOCAL throwMutexTimedLockException(const char* loc, int error_result) {
switch (error_result) {
case ( EDEADLK ): return StandardException(loc, UsageError, "DEADLOCK! The current thread already owns the mutex.");
// 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)
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.");
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.");
default : return StandardException(loc, UnknownError, "Unknown error.");
}
}
inline StandardException ECL_LOCAL throwMutexLockException(const char* loc, int error_result) {
switch (error_result) {
case ( EDEADLK ): return StandardException(loc, UsageError, "DEADLOCK! The mutex has already been locked by this thread, it now has to wait on itself.");
// 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)
case ( EBUSY ) : return StandardException(loc, ConfigurationError, "The try lock failed because it was already locked (normal operation really, not really an error).");
case ( EINVAL ) : return StandardException(loc, InvalidInputError, "The mutex does not refer to an initialised mutex.");
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.");
default : return StandardException(loc, PosixError, "Unknown error.");
}
}
inline StandardException ECL_LOCAL throwMutexUnLockException(const char* loc, int error_result) {
switch (error_result) {
case ( EINVAL ) : return StandardException(loc, InvalidInputError, "The mutex does not refer to an initialised mutex.");
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.");
case ( EPERM ) : return StandardException(loc, PermissionsError, "The user does not have the privilege to perform the operation.");
default : return StandardException(loc, UnknownError, "Unknown error.");
}
}
} // namespace threads
} // namespace ecl
#endif /* ECL_HAS_EXCEPTIONS */
#endif /* ECL_IS_POSIX */
#endif /* ECL_THREADS_MUTEX_POS_HPP_ */