Lock.h

Go to the documentation of this file.
00001 /* ES40 emulator.
00002  * Copyright (C) 2007-2008 by the ES40 Emulator Project
00003  *
00004  * WWW    : http://sourceforge.net/projects/es40
00005  * E-mail : camiel@camicom.com
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020  * 
00021  * Although this is not required, the author would appreciate being notified of, 
00022  * and receiving any modifications you may make to the source code that might serve
00023  * the general public.
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)

SourceForge.net Logo
Project space on SourceForge.net