mutex.h

Go to the documentation of this file.
00001 // OSB library ********************************************* -*- C++ -*-
00006 /*
00007   AUTHOR(S): Stephan Broennimann (vb)
00008 
00009   RCS information
00010    $Name: OSB_060808 $
00011    $Revision: 1.43 $
00012 
00013   License
00014    OSB rating and billing library for communication networks
00015    Copyright (C) 2004, 2005, 2006  OSB systems
00016 
00017    This file may be distributed and/or modify under the terms of the
00018    GNU General Public License (GPL) as published by the Free Software
00019    Foundation which is provided in the file LICENSE.GPL included in the
00020    packaging of this file.
00021 
00022    The file is distributed in the hope that it will be useful, but WITHOUT
00023    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00024    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00025    for more details.
00026 
00027    Holders of a OSB Commercial License may use this file under the terms
00028    and conditions of this commercial license.
00029  */
00030 #ifndef _MUTEX_H_
00031 #define _MUTEX_H_
00032 
00033 // *********************************************************************
00034 // included header files
00035 // + standard includes
00036 #include <deque>
00037 #include <memory>
00038 #include <pthread.h>
00039 
00040 // + local headers
00041 #include "osberror.h"
00042 #include "guard.h"
00043 
00044 // *********************************************************************
00045 // namespace extensions
00046 namespace OSB_LIB {
00047 
00048 // *********************************************************************
00049 // class definitions
00050 
00051     // *****************************************************************
00052     // class Mutex
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     // class MutexUnlock
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     // class RwMutex
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     // class RwGuard
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             // empty
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             // empty
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             // empty
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     };                                  // class ReadGuard<T*>
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             // empty
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             // empty
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             // empty
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     // template class Shared
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     };                                  // class Shared<T>
00897 
00898     // *****************************************************************
00899     // template class Shared<T*>
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     // template class RwShared
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     // template class RwShared<T*>
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 }                                       // namespace OSB_LIB
01171 #endif                                  // #ifndef _MUTEX_H_

Generated on Sat Sep 2 14:06:33 2006 for OSB Library by  doxygen 1.4.7