00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef _MUTEX_H_
00031 #define _MUTEX_H_
00032
00033
00034
00035
00036 #include <deque>
00037 #include <memory>
00038 #include <pthread.h>
00039
00040
00041 #include "osberror.h"
00042 #include "guard.h"
00043
00044
00045
00046 namespace OSB_LIB {
00047
00048
00049
00050
00051
00052
00056 class Mutex {
00057 public:
00064 Mutex(const pthread_mutexattr_t* attr = 0);
00066 ~Mutex();
00067
00077 int lock();
00078
00090 int trylock();
00091
00100 int unlock();
00101
00102 private:
00104 Mutex(const Mutex&);
00106 Mutex& operator=(const Mutex&);
00107
00109 pthread_mutex_t mutex_;
00110 };
00111
00112
00113
00119 class MutexUnlock : public Guard::Cleanup {
00120 public:
00126 explicit MutexUnlock(Mutex* pMutex = 0);
00127
00135 virtual int cleanup();
00136 private:
00142 Mutex* pMutex_;
00143 };
00144
00145
00146
00166 class RwMutex {
00167 public:
00172 enum Priority {
00174 prioRead,
00176 prioWrite,
00183 prioQueue
00184 };
00185
00196 explicit RwMutex(
00197 Priority priority = prioRead,
00198 const pthread_mutexattr_t* attr = 0
00199 );
00200
00202 ~RwMutex();
00203
00214 int readLock();
00215
00230 int tryReadLock();
00231
00242 int writeLock();
00243
00258 int tryWriteLock();
00259
00267 int readUnlock();
00268
00276 int writeUnlock();
00277
00278 private:
00280 RwMutex(const RwMutex&);
00282 RwMutex& operator=(const RwMutex&);
00283
00285 enum LockType { ltRead, ltWrite };
00287 typedef std::deque<LockType> LockQueue;
00288
00290 pthread_mutex_t mutex_;
00292 pthread_cond_t condRead_;
00294 pthread_cond_t condWrite_;
00295 int curReaders_;
00296 int curWriters_;
00297
00301 Priority priority_;
00303 LockQueue lockQueue_;
00304
00306 void addWait(LockType lt);
00308 void rmWait(LockType lt);
00310 bool canReadLock();
00312 bool canWriteLock();
00314 void sendCondition();
00315 };
00316
00317
00318
00330 class RwGuard {
00331 private:
00337 struct RwGuardRef {
00339 RwGuard& s;
00341 RwGuardRef(RwGuard& r) : s(r) {};
00342 };
00343 public:
00345 typedef int (RwMutex::*Unlock)();
00346
00363 RwGuard(
00364 bool locked = true,
00365 RwMutex* pMutex = 0,
00366 Unlock unlock = 0
00367 );
00368
00373 ~RwGuard();
00374
00379 RwGuard(RwGuard& rhs);
00380
00387 RwGuard& operator=(RwGuard rhs);
00388
00399 RwGuard(RwGuardRef r);
00403 operator RwGuardRef();
00405
00412 void unlock();
00413
00415 bool locked() const { return locked_; }
00416
00427 bool release();
00428 private:
00429 bool locked_;
00430 RwMutex* pMutex_;
00431 Unlock unlock_;
00432 };
00433
00440 template<typename T> class ReadGuard;
00441
00448 template<typename T> class ReadGuard<T*> {
00449 private:
00451 template<typename S> friend class ReadGuard;
00456 struct ReadGuardRef {
00458 ReadGuard& s;
00460 ReadGuardRef(ReadGuard& r) : s(r) {}
00461 };
00462 public:
00481 ReadGuard(
00482 const T* ptr = 0,
00483 bool locked = true,
00484 RwMutex* pMutex = 0
00485 ) : status_(), ptr_(ptr),
00486 guard_(locked, pMutex, &RwMutex::readUnlock) {}
00487
00510 explicit ReadGuard(
00511 int stat
00512 ) : status_(stat), ptr_(), guard_(false) {}
00513
00520 ReadGuard(
00521 ReadGuard& rhs
00522 ) : status_(rhs.status_),
00523 ptr_(rhs.ptr_),
00524 guard_(rhs.guard_)
00525 {
00526
00527 }
00528
00536 ReadGuard& operator=(ReadGuard rhs)
00537 {
00538 status_ = rhs.status_;
00539 ptr_ = rhs.ptr_;
00540 guard_ = rhs.guard_;
00541 return *this;
00542 }
00543
00545
00546
00551 template<typename S> ReadGuard(
00552 ReadGuard<S*> rhs
00553 ) : status_(rhs.status_),
00554 ptr_(rhs.ptr_),
00555 guard_(rhs.guard_)
00556 {
00557
00558 }
00559
00565 template<typename S> ReadGuard& operator=(
00566 ReadGuard<S*> rhs
00567 )
00568 {
00569 status_ = rhs.status_;
00570 ptr_ = rhs.ptr_;
00571 guard_ = rhs.guard_;
00572 return *this;
00573 }
00575
00582
00583 ReadGuard(
00584 ReadGuardRef r
00585 ) : status_(r.s.status_),
00586 ptr_(r.s.ptr_),
00587 guard_(r.s.guard_)
00588 {
00589
00590 }
00591
00593 operator ReadGuardRef()
00594 {
00595 ReadGuardRef rc(*this);
00596 return rc;
00597 }
00599
00607 const T* get() const
00608 {
00609 if (!locked()) return 0;
00610 return ptr_;
00611 }
00612
00618
00619 bool locked() const { return guard_.locked(); }
00620
00622 void unlock() { guard_.unlock(); }
00623
00625 bool release() { return guard_.release(); }
00627
00638 int status_;
00639
00640 private:
00642 const T* ptr_;
00644 RwGuard guard_;
00645 };
00646
00653 template<typename T> class WriteGuard;
00654
00660 template<typename T> class WriteGuard<T*> {
00661 private:
00663 template<typename S> friend class WriteGuard;
00668 struct WriteGuardRef {
00670 WriteGuard& s;
00672 WriteGuardRef(WriteGuard& r) : s(r) {}
00673 };
00674 public:
00693 WriteGuard(
00694 T* ptr = 0,
00695 bool locked = true,
00696 RwMutex* pMutex = 0
00697 ) : status_(), ptr_(ptr),
00698 guard_(locked, pMutex, &RwMutex::writeUnlock) {}
00699
00712 explicit WriteGuard(
00713 int stat
00714 ) : status_(stat), ptr_(), guard_(false) {}
00715
00722 WriteGuard(
00723 WriteGuard& rhs
00724 ) : status_(rhs.status_),
00725 ptr_(rhs.ptr_),
00726 guard_(rhs.guard_)
00727 {
00728
00729 }
00730
00738 WriteGuard& operator=(WriteGuard rhs)
00739 {
00740 status_ = rhs.status_;
00741 ptr_ = rhs.ptr_;
00742 guard_ = rhs.guard_;
00743 return *this;
00744 }
00745
00747
00748
00753 template<typename S> WriteGuard(
00754 WriteGuard<S*> rhs
00755 ) : status_(rhs.status_),
00756 ptr_(rhs.ptr_),
00757 guard_(rhs.guard_)
00758 {
00759
00760 }
00761
00767 template<typename S> WriteGuard& operator=(
00768 WriteGuard<S*> rhs
00769 )
00770 {
00771 status_ = rhs.status_;
00772 ptr_ = rhs.ptr_;
00773 guard_ = rhs.guard_;
00774 return *this;
00775 }
00777
00784
00785 WriteGuard(
00786 WriteGuardRef r
00787 ) : status_(r.s.status_),
00788 ptr_(r.s.ptr_),
00789 guard_(r.s.guard_)
00790 {
00791
00792 }
00793
00795 operator WriteGuardRef() { WriteGuardRef rc(*this); return rc; }
00797
00805 T* get()
00806 {
00807 if (!locked()) return 0;
00808 return ptr_;
00809 }
00810
00816
00817 bool locked() const { return guard_.locked(); }
00818
00820 void unlock() { guard_.unlock(); }
00821
00823 bool release() { return guard_.release(); }
00825
00836 int status_;
00837
00838 private:
00840 T* ptr_;
00842 RwGuard guard_;
00843 };
00844
00845
00846
00850 template<typename T> class Shared {
00851 public:
00853 Shared() {}
00855 Shared(const T& t) : shared_(t) {}
00856
00860 T& lock()
00861 {
00862 mutex_.lock();
00863 return shared_;
00864 }
00865
00872 T& trylock() throw(OsbException)
00873 {
00874 if (0 != mutex_.trylock()) throw DefException(112);
00875 return shared_;
00876 }
00877
00881 void unlock()
00882 {
00883 mutex_.unlock();
00884 }
00885
00886 private:
00888 Shared(const Shared&);
00890 Shared<T>& operator=(const Shared&);
00891
00893 Mutex mutex_;
00895 T shared_;
00896 };
00897
00898
00899
00903 template<typename T> class Shared<T*> {
00904 public:
00911 explicit Shared(T* t = 0)
00912 {
00913 shared_ = t;
00914 ownsShared_ = false;
00915 }
00916
00923 explicit Shared(std::auto_ptr<T> t)
00924 {
00925 shared_ = t.release();
00926 ownsShared_ = true;
00927 }
00928
00935 ~Shared() { if (ownsShared_) delete shared_; }
00936
00940 T* lock()
00941 {
00942 mutex_.lock();
00943 return shared_;
00944 }
00945
00951 T* trylock()
00952 {
00953 T* rc = 0;
00954 if (0 == mutex_.trylock()) rc = shared_;
00955 return rc;
00956 }
00957
00961 void unlock()
00962 {
00963 mutex_.unlock();
00964 }
00965
00966 private:
00968 Shared(const Shared&);
00970 Shared& operator=(const Shared&);
00971
00973 Mutex mutex_;
00975 bool ownsShared_;
00977 T* shared_;
00978 };
00979
00980
00981
00987 template<typename T> class RwShared {
00988 public:
00990 RwShared(
00991 RwMutex::Priority p = RwMutex::prioRead
00992 ) : mutex_(p) {}
00993
00995 RwShared(
00996 const T& t,
00997 RwMutex::Priority p = RwMutex::prioRead
00998 ) : shared_(t), mutex_(p) {}
00999
01001 const T& readLock()
01002 {
01003 mutex_.readLock();
01004 return shared_;
01005 }
01006
01008 const T& tryReadLock() throw(OsbException)
01009 {
01010 if (!mutex_.tryReadLock()) throw DefException(112);
01011 return shared_;
01012 }
01013
01015 T& writeLock()
01016 {
01017 mutex_.writeLock();
01018 return shared_;
01019 }
01020
01022 T& tryWriteLock() throw(OsbException)
01023 {
01024 if (!mutex_.tryWriteLock()) throw DefException(112);
01025 return shared_;
01026 }
01027
01029 void readUnlock()
01030 {
01031 mutex_.readUnlock();
01032 }
01033
01035 void writeUnlock()
01036 {
01037 mutex_.writeUnlock();
01038 }
01039
01040 private:
01042 RwShared(const RwShared&);
01044 RwShared& operator=(const RwShared&);
01045
01047 T shared_;
01049 RwMutex mutex_;
01050 };
01051
01052
01053
01057 template<typename T> class RwShared<T*> {
01058 public:
01064 RwShared(
01065 RwMutex::Priority p = RwMutex::prioRead
01066 ) : mutex_(p)
01067 {
01068 pShared_ = new T;
01069 ownsShared_ = true;
01070 }
01071
01079 RwShared(
01080 T* t,
01081 RwMutex::Priority p = RwMutex::prioRead
01082 ) : mutex_(p)
01083 {
01084 pShared_ = t;
01085 ownsShared_ = false;
01086 }
01087
01095 RwShared(
01096 std::auto_ptr<T> t,
01097 RwMutex::Priority p = RwMutex::prioRead
01098 ) : mutex_(p)
01099 {
01100 pShared_ = t.release();
01101 ownsShared_ = true;
01102 }
01103
01107 ~RwShared()
01108 {
01109 if (ownsShared_) delete pShared_;
01110 }
01111
01113 const T* readLock()
01114 {
01115 mutex_.readLock();
01116 return pShared_;
01117 }
01118
01120 const T* tryReadLock()
01121 {
01122 const T* rc = 0;
01123 if (mutex_.tryReadLock()) rc = pShared_;
01124 return rc;
01125 }
01126
01128 T* writeLock()
01129 {
01130 mutex_.writeLock();
01131 return pShared_;
01132 }
01133
01135 T* tryWriteLock()
01136 {
01137 T* rc = 0;
01138 if (mutex_.tryWriteLock()) rc = pShared_;
01139 return rc;
01140 }
01141
01143 void readUnlock()
01144 {
01145 mutex_.readUnlock();
01146 }
01147
01149 void writeUnlock()
01150 {
01151 mutex_.writeUnlock();
01152 }
01153
01154 private:
01156 RwShared(const RwShared&);
01158 RwShared& operator=(const RwShared&);
01159
01161 T* pShared_;
01166 bool ownsShared_;
01168 RwMutex mutex_;
01169 };
01170 }
01171 #endif // #ifndef _MUTEX_H_