00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "CeylanMutex.h"
00028
00029 #include <cerrno>
00030
00031
00032 #ifdef CEYLAN_USES_CONFIG_H
00033 #include "CeylanConfig.h"
00034 #endif // CEYLAN_USES_CONFIG_H
00035
00036
00037 extern "C"
00038 {
00039
00040 #ifdef CEYLAN_USES_PTHREAD_H
00041 #include <pthread.h>
00042 #endif //CEYLAN_USES_PTHREAD_H
00043
00044 }
00045
00046
00047 using std::string ;
00048
00049 using namespace Ceylan ;
00050 using namespace Ceylan::System ;
00051
00052
00053 #ifdef CEYLAN_USES_PTHREAD_H
00054
00055
00056
00057
00058 struct Mutex::SystemSpecificMutexType
00059 {
00060 pthread_mutex_t _mutex ;
00061
00062 } ;
00063
00064 #endif // CEYLAN_USES_PTHREAD_H
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 Mutex::Mutex() :
00077 Lockable(),
00078 _internalMutex( 0 )
00079 {
00080
00081 #ifdef CEYLAN_USES_PTHREAD_H
00082
00083 _internalMutex = new SystemSpecificMutexType() ;
00084
00085 ::pthread_mutex_init( & _internalMutex->_mutex, 0 ) ;
00086
00087 #else // CEYLAN_USES_PTHREAD_H
00088
00089 throw Features::FeatureNotAvailableException(
00090 "Mutex constructor: multithreading feature not available" ) ;
00091
00092 #endif //CEYLAN_USES_PTHREAD_H
00093
00094 }
00095
00096
00097
00098 Mutex::~Mutex() throw()
00099 {
00100
00101 #ifdef CEYLAN_USES_PTHREAD_H
00102
00103 if ( _internalMutex != 0 )
00104 ::pthread_mutex_destroy( & _internalMutex->_mutex ) ;
00105
00106 delete _internalMutex ;
00107
00108
00109 _internalMutex = 0 ;
00110
00111 #endif // CEYLAN_USES_PTHREAD_H
00112
00113 }
00114
00115
00116
00117 void Mutex::lock()
00118 {
00119
00120
00121 _locked = true ;
00122 postLock() ;
00123
00124 }
00125
00126
00127
00128 void Mutex::unlock()
00129 {
00130
00131
00132 preUnlock() ;
00133 _locked = false ;
00134
00135 }
00136
00137
00138
00139 void Mutex::postLock()
00140 {
00141
00142 #ifdef CEYLAN_USES_PTHREAD_H
00143
00144 ErrorCode res ;
00145
00146 if ( ( res = ::pthread_mutex_lock( & _internalMutex->_mutex ) ) != 0 )
00147 {
00148
00149 string errorMessage ;
00150
00151 switch( res )
00152 {
00153
00154 case EINVAL:
00155 errorMessage =
00156 "the mutex has not been properly initialized" ;
00157 break ;
00158
00159 case EDEADLK:
00160 errorMessage =
00161 "the mutex is already locked by the calling thread" ;
00162 break ;
00163
00164 default:
00165 errorMessage = "unknown error" ;
00166 break ;
00167
00168 }
00169
00170 throw LockException(
00171 "Mutex::postLock: effective locking failed: "
00172 + errorMessage ) ;
00173
00174
00175 }
00176
00177 #endif // CEYLAN_USES_PTHREAD_H
00178
00179 }
00180
00181
00182
00183 void Mutex::preUnlock()
00184 {
00185
00186 #ifdef CEYLAN_USES_PTHREAD_H
00187
00188 ErrorCode res ;
00189
00190
00191 if ( ( res = ::pthread_mutex_unlock( & _internalMutex->_mutex ) ) != 0 )
00192 {
00193
00194 string errorMessage ;
00195
00196 switch( res )
00197 {
00198
00199 case EINVAL:
00200 errorMessage =
00201 "the mutex has not been properly initialized" ;
00202 break ;
00203
00204 case EPERM:
00205 errorMessage =
00206 "the calling thread does not own the mutex" ;
00207 break ;
00208
00209 default:
00210 errorMessage = "unknown error" ;
00211 break ;
00212
00213 }
00214
00215 throw LockException(
00216 "Mutex::preUnlock: effective unlocking failed: "
00217 + errorMessage ) ;
00218
00219
00220 }
00221
00222 #endif // CEYLAN_USES_PTHREAD_H
00223
00224 }
00225
00226
00227
00228 const std::string Mutex::toString( Ceylan::VerbosityLevels level ) const
00229 {
00230
00231 return "Mutex, which is " + Lockable::toString( level ) ;
00232
00233 }
00234
00235
00236
00237 Mutex::SystemSpecificMutexType & Mutex::getMutexReference()
00238 {
00239
00240 return *_internalMutex ;
00241
00242 }
00243