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
00069 #if defined(NO_LOCK_TIMEOUTS)
00070 #define LOCK_TIMEOUT_MS
00071 #else
00072 #if !defined(LOCK_TIMEOUT_MS)
00073 #define LOCK_TIMEOUT_MS 5000
00074 #endif
00075 #endif
00076
00082 #define CURRENT_THREAD_NAME Poco::Thread::current() ? Poco::Thread::current() \
00083 ->getName().c_str() : "main"
00084
00091 template<class M>
00092 class CScopedLock
00093 {
00094 public:
00095 inline CScopedLock(M* mutex) { _mutex = mutex; _mutex->lock(LOCK_TIMEOUT_MS); }
00096 inline ~CScopedLock() { _mutex->unlock(); }
00097 private:
00098 M* _mutex;
00099 };
00100
00101 class CMutex : public Poco::MutexImpl
00102 {
00103 public:
00104 typedef CScopedLock<CMutex> ScopedLock;
00105 CMutex(const char* lName) { lockName = strdup(lName); };
00106 ~ CMutex() { free(lockName); };
00107 void lock();
00108 void lock(long milliseconds);
00109 bool tryLock();
00110 bool tryLock(long milliseconds);
00111 void unlock();
00112
00113 char* lockName;
00114 };
00115
00116 class CFastMutex : public Poco::FastMutexImpl
00117 {
00118 public:
00119 typedef CScopedLock<CFastMutex> ScopedLock;
00120 CFastMutex(const char* lName) { lockName = strdup(lName); };
00121 ~ CFastMutex() { free(lockName); };
00122 void lock();
00123 void lock(long milliseconds);
00124 bool tryLock();
00125 bool tryLock(long milliseconds);
00126 void unlock();
00127 char* lockName;
00128 };
00129
00130 class CScopedRWLock;
00131
00132 class CRWMutex : public Poco::RWLockImpl
00133 {
00134 public:
00135 typedef CScopedRWLock ScopedLock;
00136 CRWMutex(const char* lName) { lockName = strdup(lName); };
00137 ~ CRWMutex() { free(lockName); };
00138
00139 void readLock();
00140 bool tryReadLock();
00141 void writeLock();
00142 bool tryWriteLock();
00143 void readLock(long milliseconds);
00144 bool tryReadLock(long milliseconds);
00145 void writeLock(long milliseconds);
00146 bool tryWriteLock(long milliseconds);
00147 void unlock();
00148
00149 char* lockName;
00150 };
00151
00152 class CScopedRWLock
00153 {
00154 public:
00155 CScopedRWLock(CRWMutex* rwl, bool write = false);
00156 ~ CScopedRWLock();
00157 private:
00158 CRWMutex* _rwl;
00159 };
00160
00161 inline void CMutex::lock()
00162 {
00163 #if defined(DEBUG_LOCKS)
00164 printf(" LOCK mutex %s from thread %s. \n", lockName,
00165 CURRENT_THREAD_NAME);
00166 #endif
00167 try
00168 {
00169 lockImpl();
00170 }
00171
00172 catch(Poco::Exception & e)
00173 {
00174 FAILURE_3(Thread,
00175 "Locking error (%s) trying to lock mutex %s from thread %s.\n", e.message().c_str(),
00176 lockName, CURRENT_THREAD_NAME);
00177 }
00178
00179 #if defined(DEBUG_LOCKS)
00180 printf(" LOCKED mutex %s from thread %s. \n", lockName,
00181 CURRENT_THREAD_NAME);
00182 #endif
00183 }
00184
00185 inline void CMutex::lock(long milliseconds)
00186 {
00187 #if defined(DEBUG_LOCKS)
00188 printf(" LOCK mutex %s from thread %s. \n", lockName,
00189 CURRENT_THREAD_NAME);
00190 #endif
00191 try
00192 {
00193 if(!tryLockImpl(milliseconds))
00194 FAILURE(Timeout, "Timeout");
00195 }
00196
00197 catch(Poco::Exception & e)
00198 {
00199 FAILURE_3(Thread,
00200 "Locking error (%s) trying to lock mutex %s from thread %s.\n", e.message().c_str(),
00201 lockName, CURRENT_THREAD_NAME);
00202 }
00203
00204 #if defined(DEBUG_LOCKS)
00205 printf(" LOCKED mutex %s from thread %s. \n", lockName,
00206 CURRENT_THREAD_NAME);
00207 #endif
00208 }
00209
00210 inline bool CMutex::tryLock()
00211 {
00212 bool res;
00213 #if defined(DEBUG_LOCKS)
00214 printf(" TRY LOCK mutex %s from thread %s. \n", lockName,
00215 CURRENT_THREAD_NAME);
00216 #endif
00217 try
00218 {
00219 res = tryLockImpl();
00220 }
00221
00222 catch(Poco::Exception & e)
00223 {
00224 FAILURE_3(Thread,
00225 "Locking error (%s) trying to lock mutex %s from thread %s.\n", e.message().c_str(),
00226 lockName, CURRENT_THREAD_NAME);
00227 }
00228
00229 #if defined(DEBUG_LOCKS)
00230 printf(" %s mutex %s from thread %s. \n", res ? " LOCKED" : "CAN'T LOCK",
00231 lockName, CURRENT_THREAD_NAME);
00232 #endif
00233 return res;
00234 }
00235
00236 inline bool CMutex::tryLock(long milliseconds)
00237 {
00238 bool res;
00239 #if defined(DEBUG_LOCKS)
00240 printf(" TRY LOCK mutex %s from thread %s. \n", lockName,
00241 CURRENT_THREAD_NAME);
00242 #endif
00243 try
00244 {
00245 res = tryLockImpl(milliseconds);
00246 }
00247
00248 catch(Poco::Exception & e)
00249 {
00250 FAILURE_3(Thread,
00251 "Locking error (%s) trying to lock mutex %s from thread %s.\n", e.message().c_str(),
00252 lockName, CURRENT_THREAD_NAME);
00253 }
00254
00255 #if defined(DEBUG_LOCKS)
00256 printf(" %s mutex %s from thread %s. \n", res ? " LOCKED" : "CAN'T LOCK",
00257 lockName, CURRENT_THREAD_NAME);
00258 #endif
00259 return res;
00260 }
00261
00262 inline void CMutex::unlock()
00263 {
00264 #if defined(DEBUG_LOCKS)
00265 printf(" UNLOCK mutex %s from thread %s. \n", lockName,
00266 CURRENT_THREAD_NAME);
00267 #endif
00268 try
00269 {
00270 unlockImpl();
00271 }
00272
00273 catch(Poco::Exception & e)
00274 {
00275 FAILURE_3(Thread,
00276 "Locking error (%s) trying to unlock mutex %s from thread %s.\n",
00277 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00278 }
00279
00280 #if defined(DEBUG_LOCKS)
00281 printf(" UNLOCKED mutex %s from thread %s. \n", lockName,
00282 CURRENT_THREAD_NAME);
00283 #endif
00284 }
00285
00286 inline void CFastMutex::lock()
00287 {
00288 #if defined(DEBUG_LOCKS)
00289 printf(" LOCK mutex %s from thread %s. \n", lockName,
00290 CURRENT_THREAD_NAME);
00291 #endif
00292 try
00293 {
00294 lockImpl();
00295 }
00296
00297 catch(Poco::Exception & e)
00298 {
00299 FAILURE_3(Thread,
00300 "Locking error (%s) trying to lock mutex %s from thread %s.\n", e.message().c_str(),
00301 lockName, CURRENT_THREAD_NAME);
00302 }
00303
00304 #if defined(DEBUG_LOCKS)
00305 printf(" LOCKED mutex %s from thread %s. \n", lockName,
00306 CURRENT_THREAD_NAME);
00307 #endif
00308 }
00309
00310 inline void CFastMutex::lock(long milliseconds)
00311 {
00312 #if defined(DEBUG_LOCKS)
00313 printf(" LOCK mutex %s from thread %s. \n", lockName,
00314 CURRENT_THREAD_NAME);
00315 #endif
00316 try
00317 {
00318 if(!tryLockImpl(milliseconds))
00319 FAILURE(Timeout, "Timeout");
00320 }
00321
00322 catch(Poco::Exception & e)
00323 {
00324 FAILURE_3(Thread,
00325 "Locking error (%s) trying to lock mutex %s from thread %s.\n", e.message().c_str(),
00326 lockName, CURRENT_THREAD_NAME);
00327 }
00328
00329 #if defined(DEBUG_LOCKS)
00330 printf(" LOCKED mutex %s from thread %s. \n", lockName,
00331 CURRENT_THREAD_NAME);
00332 #endif
00333 }
00334
00335 inline bool CFastMutex::tryLock()
00336 {
00337 bool res;
00338 #if defined(DEBUG_LOCKS)
00339 printf(" TRY LOCK mutex %s from thread %s. \n", lockName,
00340 CURRENT_THREAD_NAME);
00341 #endif
00342 try
00343 {
00344 res = tryLockImpl();
00345 }
00346
00347 catch(Poco::Exception & e)
00348 {
00349 FAILURE_3(Thread,
00350 "Locking error (%s) trying to lock mutex %s from thread %s.\n", e.message().c_str(),
00351 lockName, CURRENT_THREAD_NAME);
00352 }
00353
00354 #if defined(DEBUG_LOCKS)
00355 printf(" %s mutex %s from thread %s. \n", res ? " LOCKED" : "CAN'T LOCK",
00356 lockName, CURRENT_THREAD_NAME);
00357 #endif
00358 return res;
00359 }
00360
00361 inline bool CFastMutex::tryLock(long milliseconds)
00362 {
00363 bool res;
00364 #if defined(DEBUG_LOCKS)
00365 printf(" TRY LOCK mutex %s from thread %s. \n", lockName,
00366 CURRENT_THREAD_NAME);
00367 #endif
00368 try
00369 {
00370 res = tryLockImpl(milliseconds);
00371 }
00372
00373 catch(Poco::Exception & e)
00374 {
00375 FAILURE_3(Thread,
00376 "Locking error (%s) trying to lock mutex %s from thread %s.\n", e.message().c_str(),
00377 lockName, CURRENT_THREAD_NAME);
00378 }
00379
00380 #if defined(DEBUG_LOCKS)
00381 printf(" %s mutex %s from thread %s. \n", res ? " LOCKED" : "CAN'T LOCK",
00382 lockName, CURRENT_THREAD_NAME);
00383 #endif
00384 return res;
00385 }
00386
00387 inline void CFastMutex::unlock()
00388 {
00389 #if defined(DEBUG_LOCKS)
00390 printf(" UNLOCK mutex %s from thread %s. \n", lockName,
00391 CURRENT_THREAD_NAME);
00392 #endif
00393 try
00394 {
00395 unlockImpl();
00396 }
00397
00398 catch(Poco::Exception & e)
00399 {
00400 FAILURE_3(Thread,
00401 "Locking error (%s) trying to unlock mutex %s from thread %s.\n",
00402 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00403 }
00404
00405 #if defined(DEBUG_LOCKS)
00406 printf(" UNLOCKED mutex %s from thread %s. \n", lockName,
00407 CURRENT_THREAD_NAME);
00408 #endif
00409 }
00410
00411 inline void CRWMutex::readLock()
00412 {
00413 #if defined(DEBUG_LOCKS)
00414 printf(" READ LOCK mutex %s from thread %s. \n", lockName,
00415 CURRENT_THREAD_NAME);
00416 #endif
00417 try
00418 {
00419 readLockImpl();
00420 }
00421
00422 catch(Poco::Exception & e)
00423 {
00424 FAILURE_3(Thread,
00425 "Locking error (%s) trying to read-lock mutex %s from thread %s.\n",
00426 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00427 }
00428
00429 #if defined(DEBUG_LOCKS)
00430 printf(" READ LOCKED mutex %s from thread %s. \n", lockName,
00431 CURRENT_THREAD_NAME);
00432 #endif
00433 }
00434
00435 inline bool CRWMutex::tryReadLock()
00436 {
00437 bool res;
00438 #if defined(DEBUG_LOCKS)
00439 printf(" TRY RD LOCK mutex %s from thread %s. \n", lockName,
00440 CURRENT_THREAD_NAME);
00441 #endif
00442 try
00443 {
00444 res = tryReadLockImpl();
00445 }
00446 catch(Poco::Exception & e)
00447 {
00448 FAILURE_3(Thread,
00449 "Locking error (%s) trying to read-lock mutex %s from thread %s.\n",
00450 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00451 }
00452
00453 #if defined(DEBUG_LOCKS)
00454 printf(" %s mutex %s from thread %s. \n", res ? " LOCKED" : "CAN'T LOCK",
00455 lockName, CURRENT_THREAD_NAME);
00456 #endif
00457 return res;
00458 }
00459
00460 inline bool CRWMutex::tryWriteLock(long milliseconds)
00461 {
00462 #if defined(DEBUG_LOCKS)
00463 printf(" TRY WR LOCK mutex %s from thread %s. \n", lockName,
00464 CURRENT_THREAD_NAME);
00465 #endif
00466 try
00467 {
00468 Poco::Timestamp now;
00469 Poco::Timestamp::TimeDiff diff(Poco::Timestamp::TimeDiff(milliseconds)*1000);
00470 do
00471 {
00472 if (tryWriteLock())
00473 {
00474 #if defined(DEBUG_LOCKS)
00475 printf(" WR LOCKED mutex %s from thread %s. \n", lockName, CURRENT_THREAD_NAME);
00476 #endif
00477 return true;
00478 }
00479 Poco::Thread::sleep(5);
00480 }
00481 while (!now.isElapsed(diff));
00482 #if defined(DEBUG_LOCKS)
00483 printf("CAN'T W LOCK mutex %s from thread %s. \n", lockName, CURRENT_THREAD_NAME);
00484 #endif
00485 return false;
00486 }
00487 catch(Poco::Exception & e)
00488 {
00489 FAILURE_3(Thread,
00490 "Locking error (%s) trying to write-lock mutex %s from thread %s.\n",
00491 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00492 }
00493 }
00494
00495 inline bool CRWMutex::tryReadLock(long milliseconds)
00496 {
00497 #if defined(DEBUG_LOCKS)
00498 printf(" TRY RD LOCK mutex %s from thread %s. \n", lockName,
00499 CURRENT_THREAD_NAME);
00500 #endif
00501 try
00502 {
00503 Poco::Timestamp now;
00504 Poco::Timestamp::TimeDiff diff(Poco::Timestamp::TimeDiff(milliseconds)*1000);
00505 do
00506 {
00507 if (tryReadLock())
00508 {
00509 #if defined(DEBUG_LOCKS)
00510 printf(" RD LOCKED mutex %s from thread %s. \n", lockName, CURRENT_THREAD_NAME);
00511 #endif
00512 return true;
00513 }
00514 Poco::Thread::sleep(5);
00515 }
00516 while (!now.isElapsed(diff));
00517 #if defined(DEBUG_LOCKS)
00518 printf("CAN'T R LOCK mutex %s from thread %s. \n", lockName, CURRENT_THREAD_NAME);
00519 #endif
00520 return false;
00521 }
00522 catch(Poco::Exception & e)
00523 {
00524 FAILURE_3(Thread,
00525 "Locking error (%s) trying to read-lock mutex %s from thread %s.\n",
00526 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00527 }
00528 }
00529
00530 inline void CRWMutex::writeLock(long milliseconds)
00531 {
00532 #if defined(DEBUG_LOCKS)
00533 printf(" WRITE LOCK mutex %s from thread %s. \n", lockName,
00534 CURRENT_THREAD_NAME);
00535 #endif
00536 try
00537 {
00538 Poco::Timestamp now;
00539 Poco::Timestamp::TimeDiff diff(Poco::Timestamp::TimeDiff(milliseconds)*1000);
00540 do
00541 {
00542 if (tryWriteLock())
00543 {
00544 #if defined(DEBUG_LOCKS)
00545 printf(" WR LOCKED mutex %s from thread %s. \n", lockName, CURRENT_THREAD_NAME);
00546 #endif
00547 return;
00548 }
00549 Poco::Thread::sleep(5);
00550 }
00551 while (!now.isElapsed(diff));
00552 FAILURE(Timeout, "Timeout");
00553 }
00554 catch(Poco::Exception & e)
00555 {
00556 FAILURE_3(Thread,
00557 "Locking error (%s) trying to write-lock mutex %s from thread %s.\n",
00558 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00559 }
00560 }
00561
00562 inline void CRWMutex::readLock(long milliseconds)
00563 {
00564 #if defined(DEBUG_LOCKS)
00565 printf(" READ LOCK mutex %s from thread %s. \n", lockName,
00566 CURRENT_THREAD_NAME);
00567 #endif
00568 try
00569 {
00570 Poco::Timestamp now;
00571 Poco::Timestamp::TimeDiff diff(Poco::Timestamp::TimeDiff(milliseconds)*1000);
00572 do
00573 {
00574 if (tryReadLock())
00575 {
00576 #if defined(DEBUG_LOCKS)
00577 printf(" RD LOCKED mutex %s from thread %s. \n", lockName, CURRENT_THREAD_NAME);
00578 #endif
00579 return;
00580 }
00581 Poco::Thread::sleep(5);
00582 }
00583 while (!now.isElapsed(diff));
00584 FAILURE(Timeout, "Timeout");
00585 }
00586 catch(Poco::Exception & e)
00587 {
00588 FAILURE_3(Thread,
00589 "Locking error (%s) trying to read-lock mutex %s from thread %s.\n",
00590 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00591 }
00592 }
00593
00594 inline void CRWMutex::writeLock()
00595 {
00596 #if defined(DEBUG_LOCKS)
00597 printf(" WRITE LOCK mutex %s from thread %s. \n", lockName,
00598 CURRENT_THREAD_NAME);
00599 #endif
00600 try
00601 {
00602 writeLockImpl();
00603 }
00604
00605 catch(Poco::Exception & e)
00606 {
00607 FAILURE_3(Thread,
00608 "Locking error (%s) trying to write-lock mutex %s from thread %s.\n",
00609 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00610 }
00611
00612 #if defined(DEBUG_LOCKS)
00613 printf("WRITE LOCKED mutex %s from thread %s. \n", lockName,
00614 CURRENT_THREAD_NAME);
00615 #endif
00616 }
00617
00618 inline bool CRWMutex::tryWriteLock()
00619 {
00620 bool res;
00621 #if defined(DEBUG_LOCKS)
00622 printf(" TRY WR LOCK mutex %s from thread %s. \n", lockName,
00623 CURRENT_THREAD_NAME);
00624 #endif
00625 try
00626 {
00627 res = tryWriteLockImpl();
00628 }
00629
00630 catch(Poco::Exception & e)
00631 {
00632 FAILURE_3(Thread,
00633 "Locking error (%s) trying to write-lock mutex %s from thread %s.\n",
00634 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00635 }
00636
00637 #if defined(DEBUG_LOCKS)
00638 printf(" %s mutex %s from thread %s. \n", res ? " LOCKED" : "CAN'T LOCK",
00639 lockName, CURRENT_THREAD_NAME);
00640 #endif
00641 return res;
00642 }
00643
00644 inline void CRWMutex::unlock()
00645 {
00646 #if defined(DEBUG_LOCKS)
00647 printf(" UNLOCK mutex %s from thread %s. \n", lockName,
00648 CURRENT_THREAD_NAME);
00649 #endif
00650 try
00651 {
00652 unlockImpl();
00653 }
00654
00655 catch(Poco::Exception & e)
00656 {
00657 FAILURE_3(Thread,
00658 "Locking error (%s) trying to unlock mutex %s from thread %s.\n",
00659 e.message().c_str(), lockName, CURRENT_THREAD_NAME);
00660 }
00661
00662 #if defined(DEBUG_LOCKS)
00663 printf(" UNLOCKED mutex %s from thread %s. \n", lockName,
00664 CURRENT_THREAD_NAME);
00665 #endif
00666 }
00667
00668 inline CScopedRWLock::CScopedRWLock(CRWMutex* rwl, bool write) : _rwl(rwl)
00669 {
00670 _rwl = rwl;
00671 if(write)
00672 _rwl->writeLock(LOCK_TIMEOUT_MS);
00673 else
00674 _rwl->readLock(LOCK_TIMEOUT_MS);
00675 }
00676
00677 inline CScopedRWLock::~CScopedRWLock()
00678 {
00679 _rwl->unlock();
00680 }
00681
00682 #define MUTEX_LOCK(mutex) mutex->lock(LOCK_TIMEOUT_MS)
00683 #define MUTEX_READ_LOCK(mutex) mutex->readLock(LOCK_TIMEOUT_MS)
00684 #define MUTEX_WRITE_LOCK(mutex) mutex->writeLock(LOCK_TIMEOUT_MS)
00685 #define MUTEX_UNLOCK(mutex) mutex->unlock()
00686 #define SCOPED_M_LOCK(mutex) CMutex::ScopedLock L_##__LINE__(mutex)
00687 #define SCOPED_FM_LOCK(mutex) CFastMutex::ScopedLock L_##__LINE__(mutex)
00688 #define SCOPED_READ_LOCK(mutex) CRWMutex::ScopedLock L_##__LINE__(mutex, false)
00689 #define SCOPED_WRITE_LOCK(mutex) CRWMutex::ScopedLock L_##__LINE__(mutex, true)