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 template< typename Mutex >
00100 class MutexLockT
00101 {
00102 protected:
00103 Mutex& mutex;
00104 bool locked;
00105 bool yield;
00106
00107 public:
00108 MutexLockT(Mutex& m) : mutex(m), locked( false ), yield( false ) {
00109 mutex.lock();
00110 locked = true;
00111 }
00112
00113 ~MutexLockT() {
00114 if ( locked ) {
00115 mutex.unlock();
00116 checkYield();
00117 }
00118 }
00119
00120 void drop() {
00121 mutex.unlock();
00122 locked = false;
00123 checkYield();
00124 }
00125 void reclaim() { mutex.lock(); locked = true; }
00126 void setYield( bool y ) {
00127 yield = y;
00128 }
00129
00130 void checkYield() {
00131 if ( yield )
00132 sched_yield();
00133 }
00134
00135 friend class Condition;
00136 };
00137
00138 typedef MutexLockT< Mutex > MutexLock;
00139
00140
00141
00142
00143
00144
00145 class Condition
00146 {
00147 protected:
00148 pthread_cond_t cond;
00149
00150 public:
00151 Condition()
00152 {
00153 if (int res = pthread_cond_init(&cond, 0))
00154 throw wibble::exception::System(res, "creating pthread condition");
00155 }
00156 ~Condition()
00157 {
00158 if (int res = pthread_cond_destroy(&cond))
00159 throw wibble::exception::System(res, "destroying pthread condition");
00160 }
00161
00163 void signal()
00164 {
00165 if (int res = pthread_cond_signal(&cond))
00166 throw wibble::exception::System(res, "signaling on a pthread condition");
00167 }
00168
00170 void broadcast()
00171 {
00172 if (int res = pthread_cond_broadcast(&cond))
00173 throw wibble::exception::System(res, "broadcasting on a pthread condition");
00174 }
00175
00180 void wait(MutexLock& l)
00181 {
00182 if (int res = pthread_cond_wait(&cond, &l.mutex.mutex))
00183 throw wibble::exception::System(res, "waiting on a pthread condition");
00184 }
00185
00186 void wait(Mutex& l)
00187 {
00188 if (int res = pthread_cond_wait(&cond, &l.mutex))
00189 throw wibble::exception::System(res, "waiting on a pthread condition");
00190 }
00191
00202 bool wait(MutexLock& l, const struct timespec& abstime);
00203 };
00204
00205 }
00206 }
00207
00208
00209 #endif