00001 #ifndef __RWLOCK_H__
00002 #define __RWLOCK_H__
00003
00004 #include <cstdio>
00005
00006 #include "Lock.h"
00007 #include "SpinLock.h"
00008 #include "Mutex.h"
00009
00010 namespace oasys {
00011
00017 class SXLock {
00018 public:
00019 SXLock(Lock* lock)
00020 : lock_(lock),
00021 scount_(0),
00022 xcount_(0)
00023 {}
00024
00029 void shared_lock() {
00030 lock_->lock();
00031 while (xcount_ > 0) {
00032 lock_->unlock();
00033 Thread::spin_yield();
00034 lock_->lock();
00035 }
00036 ++scount_;
00037 lock_->unlock();
00038 }
00039
00041 void shared_unlock() {
00042 lock_->lock();
00043 --scount_;
00044 lock_->unlock();
00045 }
00046
00052 void exclusive_lock() {
00053 lock_->lock();
00054 while (xcount_ > 0 && scount_ > 0) {
00055 lock_->unlock();
00056 Thread::spin_yield();
00057 lock_->lock();
00058 }
00059 ++xcount_;
00060
00061 if (xcount_ != 1) {
00062 fprintf(stderr, "more than 1 writer (%d writers) entered lock!!",
00063 xcount_);
00064 exit(-1);
00065 }
00066
00067 lock_->unlock();
00068 }
00069
00071 void exclusive_unlock() {
00072 lock_->lock();
00073
00074 --xcount_;
00075 if (xcount_ != 0) {
00076 fprintf(stderr, "more than 1 writer (%d writers) entered lock!!",
00077 xcount_);
00078 exit(-1);
00079 }
00080
00081 lock_->unlock();
00082 }
00083
00084 private:
00085 Lock* lock_;
00086
00087 int scount_;
00088 int xcount_;
00089 };
00090
00091 #define SCOPE_LOCK_DEFUN(_name, _fcn) \
00092 class ScopeLock_ ## _name { \
00093 ScopeLock_ ## _name (SXLock* rw_lock, \
00094 const char* lock_user) \
00095 : rw_lock_(rw_lock) \
00096 { \
00097 do_lock(lock_user); \
00098 } \
00099 \
00100 ScopeLock_ ## _name (ScopePtr<SXLock> rw_lock, \
00101 const char* lock_user) \
00102 : rw_lock_(rw_lock.ptr()) \
00103 { \
00104 do_lock(lock_user); \
00105 } \
00106 \
00107 ScopeLock_ ## _name (auto_ptr<SXLock> rw_lock, \
00108 const char* lock_user) \
00109 : rw_lock_(rw_lock.get()) \
00110 { \
00111 do_lock(lock_user); \
00112 } \
00113 \
00114 ~ScopeLock_ ## _name () \
00115 { \
00116 if (rw_lock_) { \
00117 do_unlock(); \
00118 } \
00119 } \
00120 \
00121 private: \
00122 SXLock* rw_lock_; \
00123 \
00124 void do_lock(const char* lock_user) { \
00125 rw_lock_->_fcn ## _lock(); \
00126 } \
00127 \
00128 void do_unlock() { \
00129 rw_lock_->_fcn ## _unlock(); \
00130 } \
00131 };
00132
00136 SCOPE_LOCK_DEFUN(Shared, shared);
00137 SCOPE_LOCK_DEFUN(Exclusive, exclusive);
00139 #undef SCOPE_LOCK_DEFUN
00140
00141 }
00142
00143 #endif