00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef ARCHON_UTILITIES_MUTEX_H
00021 #define ARCHON_UTILITIES_MUTEX_H
00022
00023 #include <errno.h>
00024 #include <pthread.h>
00025
00026 #include <archon/util/exception.H>
00027
00028 namespace Archon
00029 {
00030 namespace Utilities
00031 {
00032 using namespace std;
00033
00034 struct Thread;
00035 struct Condition;
00036
00040 struct Mutex
00041 {
00042 Mutex()
00043 {
00044 const int e = pthread_mutex_init(&mutex, 0);
00045 if(e != 0)
00046 ARCHON_THROW1(ResourceException,
00047 "Mutex initialization failed");
00048 }
00049
00050 ~Mutex()
00051 {
00052 const int e = pthread_mutex_destroy(&mutex);
00053 if(e != 0)
00054 {
00055 if(e == EBUSY)
00056 ARCHON_THROW1(StateException,
00057 "Attempt to delete a locked mutex");
00058 ARCHON_THROW1(InternalException,
00059 "Mutex destruction failed");
00060 }
00061 }
00062
00102 struct Lock
00103 {
00110 Lock(): mutex(0) {}
00111
00115 Lock(const Mutex &m): mutex(&m)
00116 {
00117 m.lock();
00118 }
00119
00120 ~Lock()
00121 {{
00122 release();
00123 }}
00124
00129 void aquire(const Mutex &m)
00130 {
00131 release();
00132 m.lock();
00133 mutex = &m;
00134 }
00135
00140 void release()
00141 {
00142 if(!mutex) return;
00143 mutex->unlock();
00144 mutex = 0;
00145 }
00146
00147 private:
00148 friend struct Thread;
00149
00150 const Mutex *mutex;
00151
00152 Lock(const Lock &);
00153 Lock &operator=(const Lock &);
00154 };
00155
00156 private:
00157 friend struct Condition;
00158
00159 pthread_mutex_t mutex;
00160
00161 Mutex(const Mutex &);
00162 Mutex &operator=(const Mutex &);
00163
00170 void lock() const
00171 {
00172 const int e =
00173 pthread_mutex_lock(const_cast<pthread_mutex_t *>(&mutex));
00174 if(e == 0) return;
00175 if(e == EDEADLK)
00176 ARCHON_THROW1(StateException,
00177 "Attempt to lock a locked mutex");
00178 if(e == EINVAL)
00179 ARCHON_THROW1(InternalException,
00180 "Attempt to lock uninitialized mutex");
00181 ARCHON_THROW1(InternalException,
00182 "Attempt to lock mutex failed");
00183 }
00184
00185 void unlock() const
00186 {
00187 const int e =
00188 pthread_mutex_unlock(const_cast<pthread_mutex_t *>(&mutex));
00189 if(e == 0) return;
00190 if(e == EPERM)
00191 ARCHON_THROW1(StateException,
00192 "Attempt to unlock mutex that is locked by another thread");
00193 if(e == EINVAL)
00194 ARCHON_THROW1(InternalException,
00195 "Attempt to unlock uninitialized mutex");
00196 ARCHON_THROW1(InternalException,
00197 "Attempt to unlock mutex failed");
00198 }
00199 };
00200 }
00201 }
00202
00203 #endif // ARCHON_UTILITIES_MUTEX_H