00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 namespace cmlabs {
00023
00024
00025
00026
00027
00028
00029 #undef HANDLE
00030 #define HANDLE pthread_cond_t*
00031
00032 JSemaphore::JSemaphore(JString semName) {
00033
00034 count=0;
00035 name = semName;
00036
00037 hSemaphore = new pthread_cond_t;
00038 pthread_cond_init(hSemaphore, NULL);
00039
00040 mutex = new pthread_mutex_t;
00041 pthread_mutex_init(mutex, NULL);
00042
00043 }
00044
00045 JSemaphore::~JSemaphore() {
00046 pthread_cond_destroy(hSemaphore);
00047 delete(hSemaphore);
00048
00049 pthread_mutex_destroy(mutex);
00050 delete(mutex);
00051 }
00052
00053
00054 bool JSemaphore::wait(long ms)
00055 {
00056 bool res;
00057 struct timeval now;
00058 struct timespec timeout;
00059 JTime t;
00060 long x;
00061 int ret = 0;
00062
00063 pthread_mutex_lock(mutex);
00064 if (count > 0) {
00065 res = true;
00066 }
00067 else if (ms < 0) {
00068 res = (pthread_cond_wait(hSemaphore, mutex) == 0);
00069 }
00070 else if (ms == 0) {
00071 calcTimeout(timeout, now, ms);
00072 ret = pthread_cond_timedwait(hSemaphore, mutex, &timeout);
00073 if (ret == EINVAL) {
00074 #ifdef DEVELOPMENT
00075
00076 #endif
00077 }
00078 res = (ret == 0);
00079 }
00080 else {
00081 calcTimeout(timeout, now, ms);
00082 ret = pthread_cond_timedwait(hSemaphore, mutex, &timeout);
00083 if (ret == EINVAL) {
00084 #ifdef DEVELOPMENT
00085
00086 #endif
00087 }
00088 res = (ret == 0);
00089 }
00090
00091 if (res) {
00092 count--;
00093 pthread_mutex_unlock(mutex);
00094
00095 return true;
00096 }
00097 else {
00098 pthread_mutex_unlock(mutex);
00099 if ((ms > 0) && (t.getAge() < (ms*0.9))) {
00100 #ifdef DEVELOPMENT
00101
00102
00103 #endif
00104 }
00105 return false;
00106 }
00107
00108
00109 }
00110
00111 bool JSemaphore::post()
00112 {
00113 pthread_mutex_lock(mutex);
00114 count++;
00115 bool res = (pthread_cond_signal(hSemaphore) == 0);
00116 pthread_mutex_unlock(mutex);
00117
00118 return res;
00119 }
00120
00121 bool JSemaphore::tryWait()
00122 {
00123 return wait(0);
00124 }
00125
00126
00127
00128
00129
00130 JSingleSemaphore::JSingleSemaphore() {
00131
00132 hSemaphore = new pthread_cond_t;
00133 pthread_cond_init(hSemaphore, NULL);
00134
00135 mutex = new pthread_mutex_t;
00136 pthread_mutex_init(mutex, NULL);
00137
00138 }
00139
00140 JSingleSemaphore::~JSingleSemaphore() {
00141 pthread_cond_destroy(hSemaphore);
00142 delete(hSemaphore);
00143
00144 pthread_mutex_destroy(mutex);
00145 delete(mutex);
00146 }
00147
00148
00149 bool JSingleSemaphore::wait(long ms)
00150 {
00151 bool res;
00152 struct timeval now;
00153 struct timespec timeout;
00154 int ret = 0;
00155 long x;
00156
00157 pthread_mutex_lock(mutex);
00158 if (ms < 0) {
00159 res = (pthread_cond_wait(hSemaphore, mutex) == 0);
00160 }
00161 else if (ms == 0) {
00162 calcTimeout(timeout, now, ms);
00163 ret = pthread_cond_timedwait(hSemaphore, mutex, &timeout);
00164 if (ret == EINVAL) {
00165
00166 }
00167 res = (ret == 0);
00168 }
00169 else {
00170 calcTimeout(timeout, now, ms);
00171 ret = pthread_cond_timedwait(hSemaphore, mutex, &timeout);
00172 if (ret == EINVAL) {
00173
00174 }
00175 res = (ret == 0);
00176 }
00177 pthread_mutex_unlock(mutex);
00178
00179 if (res) {
00180 return true;
00181 }
00182 else
00183 return false;
00184
00185
00186 }
00187
00188 bool JSingleSemaphore::postToAll()
00189 {
00190 pthread_mutex_lock(mutex);
00191 bool res = (pthread_cond_broadcast(hSemaphore) == 0);
00192 pthread_mutex_lock(mutex);
00193 return res;
00194 }
00195
00196 bool JSingleSemaphore::tryWait()
00197 {
00198 return wait(0);
00199 }
00200
00201
00202
00203
00204
00205
00206 JMutex::JMutex() {
00207
00208 pthread_mutexattr_t mattr;
00209 int ret = pthread_mutexattr_init(&mattr);
00210
00211 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
00212
00213 mutex = new pthread_mutex_t;
00214 pthread_mutex_init(mutex, &mattr);
00215
00216 semaphore = new pthread_cond_t;
00217 pthread_cond_init(semaphore, NULL);
00218
00219 semaphoremutex = new pthread_mutex_t;
00220 pthread_mutex_init(semaphoremutex, NULL);
00221 }
00222
00223 JMutex::~JMutex() {
00224 pthread_mutex_destroy(mutex);
00225 delete(mutex);
00226
00227 pthread_cond_destroy(semaphore);
00228 delete(semaphore);
00229 pthread_mutex_destroy(semaphoremutex);
00230 delete(semaphoremutex);
00231 }
00232
00233 bool JMutex::EnterMutex(long ms) const {
00234 return enterMutex(ms);
00235 }
00236
00237 bool JMutex::enterMutex(long ms) const {
00238
00239 JTime t;
00240 int res = pthread_mutex_trylock(mutex);
00241 if (res == 0) {
00242
00243 return true;
00244 }
00245
00246
00247 struct timeval now;
00248 struct timespec timeout;
00249 calcTimeout(timeout, now, ms);
00250
00251 int sres = 0;
00252 if (pthread_mutex_lock(semaphoremutex) != 0) {
00253 printf("JMutex::enterMutex failed to obtain own mutex\n");
00254 return false;
00255 }
00256 while ((res = pthread_mutex_trylock(mutex)) != 0) {
00257 if (sres == ETIMEDOUT)
00258 break;
00259 sres = pthread_cond_timedwait(semaphore, semaphoremutex, &timeout);
00260 }
00261 pthread_mutex_unlock(semaphoremutex);
00262
00263
00264 if (res == 0)
00265 return true;
00266
00267
00268
00269 return false;
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 }
00302
00303 bool JMutex::LeaveMutex() const {
00304 return leaveMutex();
00305 }
00306
00307 bool JMutex::leaveMutex() const {
00308
00309 int res = pthread_mutex_unlock(mutex);
00310 if (res == EPERM) {
00311
00312
00313
00314 return false;
00315 }
00316 else if (res != 0) {
00317 printf("JMutex::LeaveMutex failed to unlock mutex - not initialised\n");
00318 return false;
00319 }
00320
00321
00322 pthread_mutex_lock(semaphoremutex);
00323 pthread_cond_signal(semaphore);
00324 pthread_mutex_unlock(semaphoremutex);
00325
00326 return true;
00327 }
00328
00329
00330 #ifndef WIN32
00331 bool calcTimeout(struct timespec &timeout, struct timeval &now, long ms) {
00332
00333 if (gettimeofday(&now, NULL) != 0)
00334 return false;
00335 ldiv_t div_result;
00336 div_result = ldiv( ms, 1000 );
00337 timeout.tv_sec = now.tv_sec + div_result.quot;
00338 long x = now.tv_usec + (div_result.rem * 1000);
00339 if (x >= 1000000) {
00340 timeout.tv_sec++;
00341 x -= 1000000;
00342 }
00343 timeout.tv_nsec = x * 1000;
00344 return true;
00345 }
00346 #endif
00347
00348 }