00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef AMINO_UTIL_MUTEX
00018 #define AMINO_UTIL_MUTEX
00019
00020 #include <pthread.h>
00021 #include <stdexcept>
00022 #include <errno.h>
00023 #include <iostream>
00024 #include <sstream>
00025 #include <amino/cstdatomic>
00026
00027 using namespace std;
00028
00029 namespace amino{
00030 class condition_variable;
00031
00037 class mutex{
00038 protected:
00039 pthread_mutex_t fMutex;
00040 pthread_mutexattr_t attr_t;
00041
00045 mutex(bool recursive){
00046 pthread_mutexattr_init(&attr_t);
00047 pthread_mutexattr_settype(&attr_t,PTHREAD_MUTEX_RECURSIVE);
00048 pthread_mutex_init(&fMutex, &attr_t);
00049 }
00050 private:
00051
00052 const mutex & operator =(const mutex & mut){return *this;}
00053
00054 mutex(const mutex & mut){};
00055 public:
00056 typedef pthread_mutex_t * native_handle_type;
00057
00058 friend class condition_variable;
00059
00060 mutex(){
00061 pthread_mutexattr_init(&attr_t);
00062 pthread_mutexattr_settype(&attr_t,PTHREAD_MUTEX_ERRORCHECK);
00063 pthread_mutex_init(&fMutex, &attr_t);
00064 }
00065
00066 virtual ~mutex(){
00067 pthread_mutexattr_destroy(&attr_t);
00068 pthread_mutex_destroy(&fMutex);
00069 }
00070
00071 void lock(){
00072 int res = pthread_mutex_lock(&fMutex);
00073 if(0!=res){
00074 if(res == EDEADLK)
00075 throw std::range_error("dead lock");
00076 else if(res == EINVAL)
00077 throw std::range_error("mutex is not initialized correctly");
00078
00079 #ifdef DEBUG
00080 std::stringstream ss;
00081 ss<<"Can't lock "<<res<<std::endl;
00082 throw std::range_error(ss.str());
00083 #endif
00084 }
00085 }
00086
00090 bool try_lock(){
00091 int res = pthread_mutex_trylock(&fMutex);
00092 if(0==res){
00093 return true;
00094 }
00095 return false;
00096 }
00097
00098 void unlock(){
00099 int res =pthread_mutex_unlock(&fMutex);
00100 if(0!=res){
00101 if(EPERM == res)
00102 throw std::range_error("Current thread doesn't own this mutex");
00103 }
00104 }
00105
00106 native_handle_type native_handle(){
00107 return &fMutex;
00108 }
00109 };
00110
00111
00112
00113
00114
00115
00116 class recursive_mutex:public mutex{
00117 public:
00118 recursive_mutex():mutex(true){}
00119 };
00120 }
00121
00122 #endif