Webmaster  |  Imprint 
C++ Server Pages
Main  |  License  |  Documentation  |  Download 

/home/tommi/cxxtools/include/cxxtools/mutex.h

00001 /*
00002  * Copyright (C) 2005-2008 by Marc Boris Duerner
00003  * 
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  * 
00009  * As a special exception, you may use this file as part of a free
00010  * software library without restriction. Specifically, if other files
00011  * instantiate templates or use macros or inline functions from this
00012  * file, or you compile this file and link it with other files to
00013  * produce an executable, this file does not by itself cause the
00014  * resulting executable to be covered by the GNU General Public
00015  * License. This exception does not however invalidate any other
00016  * reasons why the executable file might be covered by the GNU Library
00017  * General Public License.
00018  * 
00019  * This library is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00022  * Lesser General Public License for more details.
00023  * 
00024  * You should have received a copy of the GNU Lesser General Public
00025  * License along with this library; if not, write to the Free Software
00026  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00027  */
00028 #ifndef cxxtools_Mutex_h
00029 #define cxxtools_Mutex_h
00030 
00031 #include <cxxtools/api.h>
00032 #include <cxxtools/atomicity.h>
00033 #include <cxxtools/noncopyable.h>
00034 #include <cxxtools/thread.h>
00035 
00036 namespace cxxtools {
00037 
00045 class CXXTOOLS_API Mutex : private NonCopyable
00046 {
00047     private:
00048         class MutexImpl* _impl;
00049 
00050     public:
00052         Mutex();
00053 
00059         ~Mutex();
00060 
00068         void lock();
00069 
00070         bool tryLock();
00071 
00073         void unlock();
00074 
00080         bool unlockNoThrow();
00081 
00083         MutexImpl& impl()
00084         { return *_impl;  }
00085 };
00086 
00118 class MutexLock : private NonCopyable
00119 {
00120     public:
00128         MutexLock(Mutex& m, bool doLock = true, bool isLocked = false)
00129         : _mutex(m)
00130         , _isLocked(isLocked)
00131         {
00132             if(doLock)
00133                 this->lock();
00134         }
00135 
00137         ~MutexLock()
00138         {
00139             if(_isLocked)
00140                 _mutex.unlockNoThrow();
00141         }
00142 
00143         void lock()
00144         {
00145             if(!_isLocked)
00146             {
00147                 _mutex.lock();
00148                 _isLocked = true;
00149             }
00150         }
00151 
00153         void unlock()
00154         {
00155             if(_isLocked)
00156             {
00157                 _mutex.unlock();
00158                 _isLocked = false;
00159             }
00160         }
00161 
00163         Mutex& mutex()
00164         { return _mutex; }
00165 
00167         const Mutex& mutex() const
00168         { return _mutex; }
00169 
00170         private:
00171             Mutex& _mutex;
00172             bool _isLocked;
00173 };
00174 
00177 class CXXTOOLS_API RecursiveMutex : private NonCopyable
00178 {
00179     private:
00180         class MutexImpl* _impl;
00181 
00182     public:
00183         RecursiveMutex();
00184 
00185         ~RecursiveMutex();
00186 
00187         void lock();
00188 
00189         bool tryLock();
00190 
00197         void unlock();
00198 
00199         bool unlockNoThrow();
00200 };
00201 
00204 class RecursiveLock : private NonCopyable
00205 {
00206     public:
00214         RecursiveLock(RecursiveMutex& m, bool doLock = true, bool isLocked = false)
00215         : _mutex(m)
00216         , _isLocked(isLocked)
00217         {
00218             if(doLock)
00219                 this->lock();
00220         }
00221 
00223         ~RecursiveLock()
00224         {
00225             if(_isLocked)
00226                 _mutex.unlockNoThrow();
00227         }
00228 
00229         void lock()
00230         {
00231             if(!_isLocked)
00232             {
00233                 _mutex.lock();
00234                 _isLocked = true;
00235             }
00236         }
00237 
00239         void unlock()
00240         {
00241             if(_isLocked)
00242             {
00243                 _mutex.unlock();
00244                 _isLocked = false;
00245             }
00246         }
00247 
00249         RecursiveMutex& mutex()
00250         { return _mutex; }
00251 
00253         const RecursiveMutex& mutex() const
00254         { return _mutex; }
00255 
00256         private:
00257             RecursiveMutex& _mutex;
00258             bool _isLocked;
00259 };
00260 
00266 class CXXTOOLS_API ReadWriteMutex : private NonCopyable
00267 {
00268     public:
00270         ReadWriteMutex();
00271 
00273         ~ReadWriteMutex();
00274 
00275         void readLock();
00281         bool tryReadLock();
00282 
00289         void writeLock();
00290 
00297         bool tryWriteLock();
00298 
00300         void unlock();
00301 
00302         bool unlockNoThrow();
00303 
00304     private:
00306         class ReadWriteMutexImpl* _impl;
00307 };
00308 
00309 
00310 class ReadLock : private NonCopyable
00311 {
00312     public:
00313         ReadLock(ReadWriteMutex& m, bool doLock = true, bool isLocked = false)
00314         : _mutex(m)
00315         , _locked(isLocked)
00316         {
00317             if(doLock)
00318                 this->lock();
00319         }
00320 
00321         ~ReadLock()
00322         {
00323             if(_locked)
00324                 _mutex.unlockNoThrow();
00325         }
00326 
00327         void lock()
00328         {
00329             if( ! _locked )
00330             {
00331                 _mutex.readLock();
00332                 _locked = true;
00333             }
00334         }
00335 
00336         void unlock()
00337         {
00338             if( _locked)
00339             {
00340                 _mutex.unlock();
00341                 _locked = false;
00342             }
00343         }
00344 
00345         ReadWriteMutex& mutex()
00346         { return _mutex; }
00347 
00348     private:
00349         ReadWriteMutex& _mutex;
00350         bool _locked;
00351 };
00352 
00353 
00354 class WriteLock : private NonCopyable
00355 {
00356     public:
00357         WriteLock(ReadWriteMutex& m, bool doLock = true, bool isLocked = false)
00358         : _mutex(m)
00359         , _locked(isLocked)
00360         {
00361             if(doLock)
00362                 this->lock();
00363         }
00364 
00365         ~WriteLock()
00366         {
00367             if(_locked)
00368                 _mutex.unlockNoThrow();
00369         }
00370 
00371         void lock()
00372         {
00373             if( ! _locked )
00374             {
00375                 _mutex.writeLock();
00376                 _locked = true;
00377             }
00378         }
00379 
00380         void unlock()
00381         {
00382             if( _locked)
00383             {
00384                 _mutex.unlock();
00385                 _locked = false;
00386             }
00387         }
00388 
00389         ReadWriteMutex& mutex()
00390         { return _mutex; }
00391 
00392     private:
00393         ReadWriteMutex& _mutex;
00394         bool _locked;
00395 };
00396 
00397 
00411 class SpinMutex : private NonCopyable
00412 {
00413     public:
00415         SpinMutex()
00416         : _count(0)
00417         {}
00418 
00420         ~SpinMutex()
00421         {}
00422 
00423 
00432         inline void lock()
00433         {
00434             // busy loop until unlock
00435             while( atomicCompareExchange(_count, 1, 0) )
00436             {
00437                 Thread::yield();
00438             }
00439         }
00440 
00441         bool tryLock()
00442         {
00443            return ! atomicCompareExchange(_count, 1, 0);
00444         }
00445 
00447         void unlock()
00448         {
00449             // set unlocked
00450             atomicExchange(_count, 0);
00451         }
00452 
00454         bool testIsLocked() const
00455         { return _count != 0; }
00456 
00457 private:
00458     volatile cxxtools::atomic_t _count;
00459 };
00460 
00461 
00462 class SpinLock : private NonCopyable
00463 {
00464     public:
00465         SpinLock(SpinMutex& m, bool doLock = true, bool isLocked = false)
00466         : _mutex(m)
00467         , _locked(isLocked)
00468         {
00469             if(doLock)
00470                 this->lock();
00471         }
00472 
00473         ~SpinLock()
00474         {
00475             if(_locked)
00476                 this->unlock();
00477         }
00478 
00479         void lock()
00480         {
00481             if( ! _locked )
00482             {
00483                 _mutex.lock();
00484                 _locked = true;
00485             }
00486         }
00487 
00488         void unlock()
00489         {
00490             if( _locked)
00491             {
00492                 _mutex.unlock();
00493                 _locked = false;
00494             }
00495         }
00496 
00497     private:
00498         SpinMutex& _mutex;
00499         bool _locked;
00500 };
00501 
00502 } // !namespace cxxtools
00503 
00504 #endif
Copyright © 2008 The Tntnet Development Team
Tntnet 1.6