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 #ifdef __APPLE__
00046 pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
00047 #else
00048 pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE_NP );
00049 #endif
00050 }
00051 if (int res = pthread_mutex_init(&mutex, &attr))
00052 throw wibble::exception::System(res, "creating pthread mutex");
00053 }
00054 ~Mutex()
00055 {
00056 if (int res = pthread_mutex_destroy(&mutex))
00057 throw wibble::exception::System(res, "destroying pthread mutex");
00058 }
00059
00060 bool trylock()
00061 {
00062 int res = pthread_mutex_trylock(&mutex);
00063 if ( res == EBUSY )
00064 return false;
00065 if ( res == 0 )
00066 return true;
00067 throw wibble::exception::System(res, "(try)locking pthread mutex");
00068 }
00069
00072 void lock()
00073 {
00074 if (int res = pthread_mutex_lock(&mutex))
00075 throw wibble::exception::System(res, "locking pthread mutex");
00076 }
00077
00080 void unlock()
00081 {
00082 if (int res = pthread_mutex_unlock(&mutex))
00083 throw wibble::exception::System(res, "unlocking pthread mutex");
00084 }
00085
00087 void reinit()
00088 {
00089 if (int res = pthread_mutex_init(&mutex, 0))
00090 throw wibble::exception::System(res, "reinitialising pthread mutex");
00091 }
00092
00093 friend class Condition;
00094 };
00095
00099 class MutexLock
00100 {
00101 protected:
00102 Mutex& mutex;
00103
00104 public:
00105 MutexLock(Mutex& m) : mutex(m) { mutex.lock(); }
00106 ~MutexLock() { mutex.unlock(); }
00107
00108 friend class Condition;
00109 };
00110
00111
00112
00113
00114
00115
00116 class Condition
00117 {
00118 protected:
00119 pthread_cond_t cond;
00120
00121 public:
00122 Condition()
00123 {
00124 if (int res = pthread_cond_init(&cond, 0))
00125 throw wibble::exception::System(res, "creating pthread condition");
00126 }
00127 ~Condition()
00128 {
00129 if (int res = pthread_cond_destroy(&cond))
00130 throw wibble::exception::System(res, "destroying pthread condition");
00131 }
00132
00134 void signal()
00135 {
00136 if (int res = pthread_cond_signal(&cond))
00137 throw wibble::exception::System(res, "signaling on a pthread condition");
00138 }
00139
00141 void broadcast()
00142 {
00143 if (int res = pthread_cond_broadcast(&cond))
00144 throw wibble::exception::System(res, "broadcasting on a pthread condition");
00145 }
00146
00151 void wait(MutexLock& l)
00152 {
00153 if (int res = pthread_cond_wait(&cond, &l.mutex.mutex))
00154 throw wibble::exception::System(res, "waiting on a pthread condition");
00155 }
00156
00157 void wait(Mutex& l)
00158 {
00159 if (int res = pthread_cond_wait(&cond, &l.mutex))
00160 throw wibble::exception::System(res, "waiting on a pthread condition");
00161 }
00162
00173 bool wait(MutexLock& l, const struct timespec& abstime);
00174 };
00175
00176 }
00177 }
00178
00179
00180 #endif