(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.9 and 1.13

version 1.9, 2008/08/15 23:14:01 version 1.13, 2008/09/16 18:37:03
Line 35 
Line 35 
 #include "Time.h" #include "Time.h"
 #include "PegasusAssert.h" #include "PegasusAssert.h"
 #include "Threads.h" #include "Threads.h"
   #include "Exception.h"
   #include "System.h"
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
Line 46 
Line 48 
  
 #ifdef PEGASUS_USE_POSIX_RWLOCK #ifdef PEGASUS_USE_POSIX_RWLOCK
  
 ReadWriteSem::ReadWriteSem():_readers(0), _writers(0)  ReadWriteSem::ReadWriteSem()
 { {
     pthread_rwlock_init(&_rwlock.rwlock, NULL);     pthread_rwlock_init(&_rwlock.rwlock, NULL);
     Threads::clear(_rwlock.owner);  
 } }
  
 ReadWriteSem::~ReadWriteSem() ReadWriteSem::~ReadWriteSem()
Line 62 
Line 63 
     }     }
 } }
  
 void ReadWriteSem::_wait(Boolean writeLock, ThreadType caller)  void ReadWriteSem::waitRead()
 { {
     if (writeLock)      int r = pthread_rwlock_rdlock(&_rwlock.rwlock);
     {  
         if (0 == pthread_rwlock_wrlock(&_rwlock.rwlock))      if (r != 0)
         {  
             _rwlock.owner = caller;  
             _writers++;  
             return;  
         }  
     }  
     else  
     {     {
         if (0 == pthread_rwlock_rdlock(&_rwlock.rwlock))          if (r != -1)
         {         {
             _readers++;              // Special behavior for Single UNIX Specification, Version 3
             return;              errno = r;
         }  
     }     }
  
     throw WaitFailed(Threads::self());          throw Exception(MessageLoaderParms(
               "Common.InternalException.READ_LOCK_FAILED",
               "Failed to acquire read lock: $0",
               PEGASUS_SYSTEM_ERRORMSG_NLS));
       }
 } }
  
 void ReadWriteSem::_unlock(Boolean writeLock, ThreadType caller)  void ReadWriteSem::waitWrite()
 { {
     ThreadType owner;      int r = pthread_rwlock_wrlock(&_rwlock.rwlock);
  
     if (writeLock)      if (r != 0)
     {     {
         owner = _rwlock.owner;          if (r != -1)
         Threads::clear(_rwlock.owner);  
     }  
     if (0 != pthread_rwlock_unlock(&_rwlock.rwlock))  
     {     {
         _rwlock.owner = owner;              // Special behavior for Single UNIX Specification, Version 3
         throw(Permission(Threads::self()));              errno = r;
           }
   
           throw Exception(MessageLoaderParms(
               "Common.InternalException.WRITE_LOCK_FAILED",
               "Failed to acquire write lock: $0",
               PEGASUS_SYSTEM_ERRORMSG_NLS));
     }     }
     if (!writeLock && _readers.get() != 0)  
         _readers--;  
     else if (_writers.get() != 0)  
         _writers--;  
 } }
  
 int ReadWriteSem::read_count() const  void ReadWriteSem::unlockRead()
 { {
     return _readers.get();      int rc = pthread_rwlock_unlock(&_rwlock.rwlock);
       // All documented error codes represent coding errors.
       PEGASUS_ASSERT(rc == 0);
 } }
  
 int ReadWriteSem::write_count() const  void ReadWriteSem::unlockWrite()
 { {
     return _writers.get();      int rc = pthread_rwlock_unlock(&_rwlock.rwlock);
       // All documented error codes represent coding errors.
       PEGASUS_ASSERT(rc == 0);
 } }
  
 #endif /* PEGASUS_USE_POSIX_RWLOCK */ #endif /* PEGASUS_USE_POSIX_RWLOCK */
Line 130 
Line 130 
 // 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
  
 ReadWriteSem::ReadWriteSem():_readers(0), _writers(0), _rwlock()  ReadWriteSem::ReadWriteSem() : _rwlock()
 { {
 } }
  
Line 141 
Line 141 
     {     {
         _rwlock._internal_lock.lock();         _rwlock._internal_lock.lock();
     }     }
     catch (IPCException &)      catch (...)
     {     {
         PEGASUS_ASSERT(0);         PEGASUS_ASSERT(0);
     }     }
     while (_readers.get() > 0 || _writers.get() > 0)      while (_rwlock._readers.get() > 0 || _rwlock._writers.get() > 0)
     {     {
         Threads::yield();         Threads::yield();
     }     }
     _rwlock._internal_lock.unlock();     _rwlock._internal_lock.unlock();
 } }
  
 //---------------------------------------------------------------------  void ReadWriteSem::waitRead()
 void ReadWriteSem::_wait(Boolean writeLock, ThreadType caller)  
 { {
 //-----------------------------------------------------------------      // Lock the internal mutex to ensure only one waiter is processed at a time.
 // Lock this object to maintain integrity while we decide      AutoMutex lock(_rwlock._internal_lock);
 // exactly what to do next.  
 //-----------------------------------------------------------------  
     _rwlock._internal_lock.lock();  
  
     if (writeLock)      // Wait for the existing writer (if any) to clear.
       while (_rwlock._writers.get() > 0)
     {     {
 //-----------------------------------------------------------------  
 // Write Lock Step 1: lock the object and allow all the readers to exit  
 //-----------------------------------------------------------------  
         while (_readers.get() > 0)  
             Threads::yield();             Threads::yield();
 //-----------------------------------------------------------------  
 // Write Lock Step 2: Obtain the Write Mutex  
 //  Although there are no readers, there may be a writer  
 //-----------------------------------------------------------------  
         try  
         {  
             _rwlock._wlock.lock();  
         }  
         catch (const IPCException&)  
         {  
             _rwlock._internal_lock.unlock();  
             throw;  
         }  
 //-----------------------------------------------------------------  
 // Write Lock Step 3: set the writer count to one, unlock the object  
 //   There are no readers and we are the only writer !  
 //-----------------------------------------------------------------  
         _writers = 1;  
         // set the owner  
         _rwlock._owner = Threads::self();  
         // unlock the object  
         _rwlock._internal_lock.unlock();  
     }     }
     else  
     {      // Wait for a reader slot to open up.
 //-----------------------------------------------------------------  
 // Read Lock Step 1: Wait for the existing writer (if any) to clear  
 //-----------------------------------------------------------------  
         while (_writers.get() > 0)  
             Threads::yield();  
 //-----------------------------------------------------------------  
 // 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  
 //  readers.  
 //-----------------------------------------------------------------  
         try  
         {  
             _rwlock._rlock.wait();             _rwlock._rlock.wait();
         }  
         catch (const IPCException&)      // Increment the number of readers.
         {      _rwlock._readers++;
             _rwlock._internal_lock.unlock();  
             throw;  
         }  
 //-----------------------------------------------------------------  
 // Read Lock Step 3: increment the number of readers, unlock the object,  
 // return  
 //-----------------------------------------------------------------  
         _readers++;  
         _rwlock._internal_lock.unlock();  
     }  
 } }
  
 void ReadWriteSem::_unlock(Boolean writeLock, ThreadType caller)  void ReadWriteSem::waitWrite()
 {  
     if (writeLock && _writers.get() != 0)  
     {     {
         _writers = 0;      // Lock the internal mutex to ensure only one waiter is processed at a time.
         _rwlock._wlock.unlock();      AutoMutex lock(_rwlock._internal_lock);
     }  
     else if (_readers.get() != 0)      // Allow all the readers to exit.
       while (_rwlock._readers.get() > 0)
     {     {
         _readers--;          Threads::yield();
         _rwlock._rlock.signal();  
     }     }
   
       // Obtain the write mutex.
       _rwlock._wlock.lock();
   
       // Set the writer count to one.
       _rwlock._writers = 1;
 } }
  
 int ReadWriteSem::read_count() const  void ReadWriteSem::unlockRead()
 { {
     return _readers.get();      PEGASUS_ASSERT(_rwlock._readers.get() > 0);
       _rwlock._readers--;
       _rwlock._rlock.signal();
 } }
  
 int ReadWriteSem::write_count() const  void ReadWriteSem::unlockWrite()
 { {
     return _writers.get();      PEGASUS_ASSERT(_rwlock._writers.get() == 1);
       _rwlock._writers = 0;
       _rwlock._wlock.unlock();
 } }
  
 #endif /* !PEGASUS_USE_SEMAPHORE_RWLOCK */ #endif /* !PEGASUS_USE_SEMAPHORE_RWLOCK */


Legend:
Removed from v.1.9  
changed lines
  Added in v.1.13

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2