Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

atoms/rwmutex.hh

Go to the documentation of this file.
00001 
00009 #ifndef ATOMS_RWMUTEX_HH
00010 #define ATOMS_RWMUTEX_HH
00011 
00012 #include <atoms/gen.hh>
00013 #include <pthread.h>
00014 #ifndef PTHREAD_RWLOCK_INITIALIZER
00015 #include <boost/static_assert.hpp>
00016 #include <boost/integer_traits.hpp>
00017 #include <atoms/mutex.hh>
00018 #include <atoms/thread.hh> // for Condition
00019 #endif
00020 
00021 namespace atoms {
00022 
00030 class RWMutex : boost::noncopyable {
00031 public:
00032     RWMutex() :
00033 #ifdef PTHREAD_RWLOCK_INITIALIZER
00034         me(PTHREAD_RWLOCK_INITIALIZER)
00035 #else
00036         active(0), numBlockedWriters(0)
00037 #endif
00038         {}
00039 
00040     class ReadMon : public Monitor {
00041     public:
00042         ReadMon(RWMutex &m);
00043         ~ReadMon();
00044     private:
00045         RWMutex &m;
00046     };
00047 
00048     class WriteMon : public Monitor {
00049     public:
00050         WriteMon(RWMutex &m);
00051         ~WriteMon();
00052     private:
00053         RWMutex &m;
00054     };
00055 private:
00056 #ifdef PTHREAD_RWLOCK_INITIALIZER
00057     pthread_rwlock_t me;
00058 #else
00059     const static unsigned short MAX_ACTIVE_READERS = 16;
00060     Mutex m;
00061     unsigned short active;
00062     unsigned short numBlockedWriters;
00063     Condition writerCondition;
00064     Condition readerCondition;
00065 #endif
00066 };
00067 
00068 #ifdef PTHREAD_RWLOCK_INITIALIZER
00069 RWMutex::ReadMon::ReadMon(RWMutex &m) : m(m) {
00070     int retval = pthread_rwlock_rdlock(&mm.me);
00071     assert(retval == 0);
00072 }
00073 
00074 RWMutex::ReadMon::~ReadMon() {
00075     int retval = pthread_rwlock_unlock(&mm.me);
00076     assert(retval == 0);
00077 }
00078 
00079 RWMutex::WriteMon::WriteMon(RWMutex &m) : m(m) {
00080     int retval = pthread_rwlock_wrlock(&&m.me);
00081     assert(retval == 0);
00082 }
00083 
00084 RWMutex::WriteMon::~WriteMon() {
00085     int retval = pthread_rwlock_unlock(&mm.me);
00086     assert(retval == 0);
00087 }
00088 #else 
00089 inline RWMutex::ReadMon::ReadMon(RWMutex &m) : m(m) {
00090     Mutex::Mon mm(m.m);
00091     while (m.active == MAX_ACTIVE_READERS || m.numBlockedWriters > 0) {
00092         m.readerCondition.wait(mm);
00093     }
00094     m.active++;
00095 }
00096 
00097 inline RWMutex::ReadMon::~ReadMon() {
00098     Mutex::Mon mm(m.m);
00099     assert(m.active > 0);
00100     if (m.numBlockedWriters > 0) {
00101         m.writerCondition.signal();
00102     } else if (m.active-- == MAX_ACTIVE_READERS) {
00103         m.readerCondition.signal();
00104     }
00105 }
00106 
00107 inline RWMutex::WriteMon::WriteMon(RWMutex &m) : m(m) {
00108     Mutex::Mon mm(m.m);
00109     while (m.active > 0) {
00110         if (++m.numBlockedWriters == 0) {
00111             // Wrapped; too many writers.
00112             abort();
00113         }
00114         try {
00115             m.writerCondition.wait(mm);
00116         } catch (...) {
00117             if (--m.numBlockedWriters == 0) {
00118                 m.readerCondition.broadcast();
00119             }
00120             throw;
00121         }
00122         m.numBlockedWriters--;
00123     }
00124     m.active = MAX_ACTIVE_READERS;
00125 }
00126 
00127 inline RWMutex::WriteMon::~WriteMon() {
00128     Mutex::Mon mm(m.m);
00129     assert(m.active == MAX_ACTIVE_READERS);
00130     m.active = 0;
00131     if (m.numBlockedWriters > 0) {
00132         m.writerCondition.signal();
00133     } else {
00134         m.readerCondition.broadcast();
00135     }
00136 }
00137 #endif 
00138 
00139 } // namespace atoms
00140 
00141 #endif // !ATOMS_RWMUTEX_HH

Generated on Wed Jun 15 01:20:35 2005 for atoms++ by doxygen 1.3.5