00001 #ifndef WIBBLE_SYS_MUTEX_H
00002 #define WIBBLE_SYS_MUTEX_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <wibble/exception.h>
00025 #include <pthread.h>
00026 #include <errno.h>
00027
00028 namespace wibble {
00029 namespace sys {
00030
00034 class Mutex
00035 {
00036 protected:
00037 pthread_mutex_t mutex;
00038
00039 public:
00040 Mutex(bool recursive = false)
00041 {
00042 pthread_mutexattr_t attr;
00043 pthread_mutexattr_init( &attr );
00044 if ( recursive ) {
00045 pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE_NP );
00046 }
00047 if (int res = pthread_mutex_init(&mutex, &attr))
00048 throw wibble::exception::System(res, "creating pthread mutex");
00049 }
00050 ~Mutex()
00051 {
00052 if (int res = pthread_mutex_destroy(&mutex))
00053 throw wibble::exception::System(res, "destroying pthread mutex");
00054 }
00055
00056 bool trylock()
00057 {
00058 int res = pthread_mutex_trylock(&mutex);
00059 if ( res == EBUSY )
00060 return false;
00061 if ( res == 0 )
00062 return true;
00063 throw wibble::exception::System(res, "(try)locking pthread mutex");
00064 }
00065
00068 void lock()
00069 {
00070 if (int res = pthread_mutex_lock(&mutex))
00071 throw wibble::exception::System(res, "locking pthread mutex");
00072 }
00073
00076 void unlock()
00077 {
00078 if (int res = pthread_mutex_unlock(&mutex))
00079 throw wibble::exception::System(res, "unlocking pthread mutex");
00080 }
00081
00083 void reinit()
00084 {
00085 if (int res = pthread_mutex_init(&mutex, 0))
00086 throw wibble::exception::System(res, "reinitialising pthread mutex");
00087 }
00088
00089 friend class Condition;
00090 };
00091
00095 class MutexLock
00096 {
00097 protected:
00098 Mutex& mutex;
00099
00100 public:
00101 MutexLock(Mutex& m) : mutex(m) { mutex.lock(); }
00102 ~MutexLock() { mutex.unlock(); }
00103
00104 friend class Condition;
00105 };
00106
00107
00108
00109
00110
00111
00112 class Condition
00113 {
00114 protected:
00115 pthread_cond_t cond;
00116
00117 public:
00118 Condition()
00119 {
00120 if (int res = pthread_cond_init(&cond, 0))
00121 throw wibble::exception::System(res, "creating pthread condition");
00122 }
00123 ~Condition()
00124 {
00125 if (int res = pthread_cond_destroy(&cond))
00126 throw wibble::exception::System(res, "destroying pthread condition");
00127 }
00128
00130 void signal()
00131 {
00132 if (int res = pthread_cond_signal(&cond))
00133 throw wibble::exception::System(res, "signaling on a pthread condition");
00134 }
00135
00137 void broadcast()
00138 {
00139 if (int res = pthread_cond_broadcast(&cond))
00140 throw wibble::exception::System(res, "broadcasting on a pthread condition");
00141 }
00142
00147 void wait(MutexLock& l)
00148 {
00149 if (int res = pthread_cond_wait(&cond, &l.mutex.mutex))
00150 throw wibble::exception::System(res, "waiting on a pthread condition");
00151 }
00152
00153 void wait(Mutex& l)
00154 {
00155 if (int res = pthread_cond_wait(&cond, &l.mutex))
00156 throw wibble::exception::System(res, "waiting on a pthread condition");
00157 }
00158
00169 bool wait(MutexLock& l, const struct timespec& abstime);
00170 };
00171
00172 }
00173 }
00174
00175
00176 #endif