(file) Return to ReadWriteSem.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

Diff for /pegasus/src/Pegasus/Common/ReadWriteSem.cpp between version 1.1.2.6 and 1.7

version 1.1.2.6, 2006/07/28 21:19:53 version 1.7, 2008/03/05 22:25:17
Line 29 
Line 29 
 // //
 //============================================================================== //==============================================================================
 // //
 // Author: Mike Day (mdday@us.ibm.com)  
 //  
 // Reworked By: Mike Brasher (m.brasher@inovadevelopment.com)  
 //  
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include "ReadWriteSem.h" #include "ReadWriteSem.h"
 #include "Time.h" #include "Time.h"
 #include "PegasusAssert.h" #include "PegasusAssert.h"
   #include "Threads.h"
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
   
 //============================================================================== //==============================================================================
 // //
 // PEGASUS_USE_POSIX_RWLOCK // PEGASUS_USE_POSIX_RWLOCK
 // //
 //============================================================================== //==============================================================================
   
 #ifdef PEGASUS_USE_POSIX_RWLOCK #ifdef PEGASUS_USE_POSIX_RWLOCK
   
 ReadWriteSem::ReadWriteSem():_readers(0), _writers(0) ReadWriteSem::ReadWriteSem():_readers(0), _writers(0)
 { {
     pthread_rwlock_init(&_rwlock.rwlock, NULL);     pthread_rwlock_init(&_rwlock.rwlock, NULL);
Line 54 
Line 54 
  
 ReadWriteSem::~ReadWriteSem() ReadWriteSem::~ReadWriteSem()
 { {
       int r = 0;
     while (EBUSY == pthread_rwlock_destroy(&_rwlock.rwlock))      while ((r = pthread_rwlock_destroy(&_rwlock.rwlock)) == EBUSY ||
              (r == -1 && errno == EBUSY))
     {     {
         Threads::yield();         Threads::yield();
     }     }
Line 90 
Line 91 
         throw(WaitFailed(Threads::self()));         throw(WaitFailed(Threads::self()));
 } }
  
 void ReadWriteSem::try_wait(Uint32 mode, ThreadType caller)  
 {  
     int errorcode = 0;  
     if (mode == PEG_SEM_READ)  
     {  
         if (0 == (errorcode = pthread_rwlock_tryrdlock(&_rwlock.rwlock)))  
         {  
             _readers++;  
             return;  
         }  
     }  
     else if (mode == PEG_SEM_WRITE)  
     {  
         if (0 == (errorcode = pthread_rwlock_trywrlock(&_rwlock.rwlock)))  
         {  
             _writers++;  
             _rwlock.owner = caller;  
             return;  
         }  
     }  
     else  
         throw(Permission(Threads::self()));  
   
     if (errorcode == EBUSY)  
         throw(AlreadyLocked(_rwlock.owner));  
     else if (errorcode == EDEADLK)  
         throw(Deadlock(_rwlock.owner));  
     else  
         throw(WaitFailed(Threads::self()));  
 }  
   
   
 // timedrdlock and timedwrlock are not supported on HPUX  
 // mdday Sun Aug  5 14:21:00 2001  
 void ReadWriteSem::timed_wait(Uint32 mode,  
                               ThreadType caller, int milliseconds)  
 {  
     int errorcode = 0, timeout;  
     struct timeval now, finish, remaining;  
     Uint32 usec;  
   
     gettimeofday(&finish, NULL);  
     finish.tv_sec += (milliseconds / 1000);  
     milliseconds %= 1000;  
     usec = finish.tv_usec + (milliseconds * 1000);  
     finish.tv_sec += (usec / 1000000);  
     finish.tv_usec = usec % 1000000;  
   
     if (mode == PEG_SEM_READ)  
     {  
         do  
         {  
             errorcode = pthread_rwlock_tryrdlock(&_rwlock.rwlock);  
             gettimeofday(&now, NULL);  
         }  
         while (errorcode == EBUSY &&  
                (0 == (timeout = Time::subtract(&remaining, &finish, &now))));  
         if (0 == errorcode)  
         {  
             _readers++;  
             return;  
         }  
     }  
     else if (mode == PEG_SEM_WRITE)  
     {  
         do  
         {  
             errorcode = pthread_rwlock_trywrlock(&_rwlock.rwlock);  
             gettimeofday(&now, NULL);  
         }  
         while (errorcode == EBUSY &&  
                (0 == (timeout = Time::subtract(&remaining, &finish, &now))));  
   
         if (0 == errorcode)  
         {  
             _writers++;  
             _rwlock.owner = caller;  
             return;  
         }  
     }  
     else  
         throw(Permission(Threads::self()));  
     if (timeout != 0)  
         throw(TimeOut(_rwlock.owner));  
     else if (errorcode == EDEADLK)  
         throw(Deadlock(_rwlock.owner));  
     else  
         throw(WaitFailed(Threads::self()));  
 }  
   
 void ReadWriteSem::unlock(Uint32 mode, ThreadType caller) void ReadWriteSem::unlock(Uint32 mode, ThreadType caller)
 { {
     ThreadType owner;     ThreadType owner;
Line 202 
Line 113 
  
 int ReadWriteSem::read_count() const int ReadWriteSem::read_count() const
 { {
 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)      return _readers.get();
     PEGASUS_ASSERT(_readers.get() == _rwlock.rwlock.__rw_readers);  
 #endif  
     return (_readers.get());  
 } }
  
 int ReadWriteSem::write_count() const int ReadWriteSem::write_count() const
 { {
 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)      return _writers.get();
     if (_rwlock.rwlock.__rw_writer != NULL)  
     {  
         PEGASUS_ASSERT(_writers.get() == 1);  
     }  
 #endif  
     return (_writers.get());  
 } }
  
 #endif /* PEGASUS_USE_POSIX_RWLOCK */ #endif /* PEGASUS_USE_POSIX_RWLOCK */
Line 234 
Line 136 
 // 2) I do not hold the write lock // 2) I do not hold the write lock
 // 3) I am not using a reader slot // 3) I am not using a reader slot
  
 void extricate_read_write(void *parm)  
 {  
     ReadWriteSem *rws = (ReadWriteSem *) parm;  
     ThreadType myself = Threads::self();  
   
     if (Threads::equal(rws->_rwlock._wlock.get_owner(), myself))  
         rws->_rwlock._wlock.unlock();  
     else if (rws->_readers.get() > 0)  
         rws->_rwlock._rlock.signal();  
   
     if (Threads::equal(rws->_rwlock._internal_lock.get_owner(), myself))  
         rws->_rwlock._internal_lock.unlock();  
 }  
   
   
 ReadWriteSem::ReadWriteSem():_readers(0), _writers(0), _rwlock() ReadWriteSem::ReadWriteSem():_readers(0), _writers(0), _rwlock()
 { {
 } }
Line 258 
Line 145 
     // lock everyone out of this object     // lock everyone out of this object
     try     try
     {     {
         _rwlock._internal_lock.lock(Threads::self());          _rwlock._internal_lock.lock();
     }     }
     catch(Deadlock & d)      catch (Deadlock &)
     {     {
         d = d;                  // no problem - we own the lock, which is          // no problem - we own the lock, which is what we want
                                 // what we want  
     }     }
     catch(IPCException &)     catch(IPCException &)
     {     {
Line 276 
Line 162 
     _rwlock._internal_lock.unlock();     _rwlock._internal_lock.unlock();
 } }
  
   //---------------------------------------------------------------------
   void ReadWriteSem::wait(Uint32 mode, ThreadType caller)
   
   
   
 //-----------------------------------------------------------------  
 // if milliseconds == -1, wait indefinately  
 // if milliseconds == 0, fast wait  
 //-----------------------------------------------------------------  
 void ReadWriteSem::timed_wait(Uint32 mode, ThreadType caller,  
                               int milliseconds)  
 { {
   
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 // Lock this object to maintain integrity while we decide // Lock this object to maintain integrity while we decide
 // exactly what to do next. // exactly what to do next.
Line 307 
Line 183 
  
     // cleanup stack frame     // cleanup stack frame
     {     {
           // Threads::cleanup_push(extricate_read_write, this);
         Threads::cleanup_push(extricate_read_write, this);  
  
         try         try
         {         {
             if (milliseconds == 0)                  _rwlock._internal_lock.lock();
                 _rwlock._internal_lock.try_lock(Threads::self());  
             else if (milliseconds == -1)  
                 _rwlock._internal_lock.lock(Threads::self());  
             else  
                 _rwlock._internal_lock.timed_lock(milliseconds,  
                                                   Threads::self());  
         }         }
         catch(const IPCException & e)         catch(const IPCException & e)
         {         {
Line 331 
Line 200 
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 // Write Lock Step 1: lock the object and allow all the readers to exit // Write Lock Step 1: lock the object and allow all the readers to exit
 //----------------------------------------------------------------- //-----------------------------------------------------------------
   
   
             if (milliseconds == 0)      // fast wait  
             {  
                 if (_readers.get() > 0)  
                 {  
                     _rwlock._internal_lock.unlock();  
                     // caught.reset(new WaitFailed(Threads::self()));  
                     caughtWaitFailed = WaitFailed(Threads::self());  
                     goto throw_from_here;  
                 }  
             }  
             else if (milliseconds == -1)        // infinite wait  
             {  
                 while (_readers.get() > 0)                 while (_readers.get() > 0)
                     Threads::yield();                     Threads::yield();
             }  
             else                // timed wait  
             {  
                 struct timeval start, now;  
                 Time::gettimeofday(&start);  
                 start.tv_usec += (1000 * milliseconds);  
                 while (_readers.get() > 0)  
                 {  
                     Time::gettimeofday(&now);  
                     if ((now.tv_usec > start.tv_usec) ||  
                         now.tv_sec > start.tv_sec)  
                     {  
                         _rwlock._internal_lock.unlock();  
                         // caught.reset(new TimeOut(Threads::self()));  
                         caughtTimeOut = TimeOut(Threads::self());  
                         goto throw_from_here;  
                     }  
                     Threads::yield();  
                 }  
             }  
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 // Write Lock Step 2: Obtain the Write Mutex // Write Lock Step 2: Obtain the Write Mutex
 //  Although there are no readers, there may be a writer //  Although there are no readers, there may be a writer
 //----------------------------------------------------------------- //-----------------------------------------------------------------
             if (milliseconds == 0)      // fast wait  
             {  
                 try  
                 {  
                     _rwlock._wlock.try_lock(Threads::self());  
                 }  
                 catch(IPCException & e)  
                 {  
                     _rwlock._internal_lock.unlock();  
                     caught = e;  
                     goto throw_from_here;  
                 }  
             }  
             else if (milliseconds == -1)        // infinite wait  
             {  
                 try  
                 {  
                     _rwlock._wlock.lock(Threads::self());  
                 }  
                 catch(const IPCException & e)  
                 {  
                     _rwlock._internal_lock.unlock();  
                     caught = e;  
                     goto throw_from_here;  
                 }  
             }  
             else                // timed wait  
             {  
                 try                 try
                 {                 {
                     _rwlock._wlock.timed_lock(milliseconds, Threads::self());                  _rwlock._wlock.lock();
                 }                 }
                 catch(const IPCException & e)                 catch(const IPCException & e)
                 {                 {
Line 409 
Line 216 
                     caught = e;                     caught = e;
                     goto throw_from_here;                     goto throw_from_here;
                 }                 }
             }  
   
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 // Write Lock Step 3: set the writer count to one, unlock the object // Write Lock Step 3: set the writer count to one, unlock the object
 //   There are no readers and we are the only writer ! //   There are no readers and we are the only writer !
Line 426 
Line 231 
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 // Read Lock Step 1: Wait for the existing writer (if any) to clear // Read Lock Step 1: Wait for the existing writer (if any) to clear
 //----------------------------------------------------------------- //-----------------------------------------------------------------
             if (milliseconds == 0)      // fast wait  
             {  
                 if (_writers.get() > 0)  
                 {  
                     _rwlock._internal_lock.unlock();  
                     // caught.reset(new WaitFailed(Threads::self()));  
                     caughtWaitFailed = WaitFailed(Threads::self());  
                     goto throw_from_here;  
                 }  
             }  
             else if (milliseconds == -1)        // infinite wait  
             {  
                 while (_writers.get() > 0)  
                     Threads::yield();  
             }  
             else                // timed wait  
             {  
                 struct timeval start, now;  
                 Time::gettimeofday(&start);  
                 start.tv_usec += (milliseconds * 1000);  
   
                 while (_writers.get() > 0)                 while (_writers.get() > 0)
                 {  
                     Time::gettimeofday(&now);  
                     if ((now.tv_usec > start.tv_usec) ||  
                         (now.tv_sec > start.tv_sec))  
                     {  
                         _rwlock._internal_lock.unlock();  
                         // caught.reset(new TimeOut(Threads::self()));  
                         caughtTimeOut = TimeOut(Threads::self());  
                         goto throw_from_here;  
                     }  
                     Threads::yield();                     Threads::yield();
                     Time::gettimeofday(&now);  
                 }  
             }  
   
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 // Read Lock Step 2: wait for a reader slot to open up, then return // Read Lock Step 2: wait for a reader slot to open up, then return
 //  At this point there are no writers, but there may be too many //  At this point there are no writers, but there may be too many
 //  readers. //  readers.
 //----------------------------------------------------------------- //-----------------------------------------------------------------
             if (milliseconds == 0)      // fast wait  
             {  
                 try  
                 {  
                     _rwlock._rlock.try_wait();  
                 }  
                 catch(const IPCException &)  
                 {  
                     // the wait failed, there must be too many readers  
                     // already.  
                     // unlock the object  
                     caughtTooManyReaders = TooManyReaders(Threads::self());  
                     _rwlock._internal_lock.unlock();  
                     // caught.reset(new TooManyReaders(Threads::self()));  
                 }  
             }  
             else if (milliseconds == -1)        // infinite wait  
             {  
                 try                 try
                 {                 {
                     _rwlock._rlock.wait();                     _rwlock._rlock.wait();
Line 496 
Line 248 
                     caught = e;                     caught = e;
                     goto throw_from_here;                     goto throw_from_here;
                 }                 }
             }  
             else                // timed wait  
             {  
                 try  
                 {  
                     _rwlock._rlock.time_wait(milliseconds);  
                 }  
                 catch(const IPCException & e)  
                 {  
                     _rwlock._internal_lock.unlock();  
                     caught = e;  
                     goto throw_from_here;  
                 }  
             }  
   
 //----------------------------------------------------------------- //-----------------------------------------------------------------
 // Read Lock Step 3: increment the number of readers, unlock the object, // Read Lock Step 3: increment the number of readers, unlock the object,
 // return // return
Line 522 
Line 259 
         // ATTN:         // ATTN:
         Threads::cleanup_pop(0);         Threads::cleanup_pop(0);
     }     }
       if (!Threads::null(caught.get_owner()))
     if (Threads::id(caught.get_owner()) != 0)  
         throw caught;         throw caught;
     if (Threads::id(caughtWaitFailed.get_owner()) != 0)      if (!Threads::null(caughtWaitFailed.get_owner()))
         throw caughtWaitFailed;         throw caughtWaitFailed;
     if (Threads::id(caughtTimeOut.get_owner()) != 0)      if (!Threads::null(caughtTimeOut.get_owner()))
         throw caughtTimeOut;         throw caughtTimeOut;
     if (Threads::id(caughtTooManyReaders.get_owner()) != 0)      if (!Threads::null(caughtTooManyReaders.get_owner()))
   
         throw caughtTooManyReaders;         throw caughtTooManyReaders;
     return;     return;
 } }
  
 //---------------------------------------------------------------------  
 void ReadWriteSem::wait(Uint32 mode, ThreadType caller)  
 {  
     timed_wait(mode, caller, -1);  
 }  
   
 void ReadWriteSem::try_wait(Uint32 mode, ThreadType caller)  
 {  
     timed_wait(mode, caller, 0);  
 }  
   
   
 void ReadWriteSem::unlock(Uint32 mode, ThreadType caller) void ReadWriteSem::unlock(Uint32 mode, ThreadType caller)
 { {
     if (mode == PEG_SEM_WRITE && _writers.get() != 0)     if (mode == PEG_SEM_WRITE && _writers.get() != 0)
Line 562 
Line 287 
  
 int ReadWriteSem::read_count() const int ReadWriteSem::read_count() const
 { {
     return (_readers.get());      return _readers.get();
 } }
  
 int ReadWriteSem::write_count() const int ReadWriteSem::write_count() const
 { {
     return (_writers.get());      return _writers.get();
 } }
  
 #endif /* !PEGASUS_USE_SEMAPHORE_RWLOCK */ #endif /* !PEGASUS_USE_SEMAPHORE_RWLOCK */


Legend:
Removed from v.1.1.2.6  
changed lines
  Added in v.1.7

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2