lightMutex.h
Go to the documentation of this file.
00001 /* lightMutex.h
00002  */
00003 #ifndef OSL_LIGHT_MUTEX_H
00004 #define OSL_LIGHT_MUTEX_H
00005 
00006 #include "osl/oslConfig.h"
00007 #ifdef PROFILE_MUTEX
00008 #  include "osl/misc/perfmon.h"
00009 #endif
00010 #include <boost/thread.hpp>
00011 #include <boost/utility.hpp>
00012 
00013 namespace osl
00014 {
00015   namespace misc
00016   {
00017 #if defined OSL_USE_RACE_DETECTOR || defined _MSC_VER
00018     typedef boost::mutex LightMutex;
00019     typedef boost::mutex LightMutexChar;
00020 #else
00021     template <class Mutex>
00022     class LightScopedLock : boost::noncopyable {
00023       Mutex& m;
00024     public:
00025 #ifdef PROFILE_MUTEX
00026       LightScopedLock(osl::misc::CounterPair &c,Mutex& m) :m(m){
00027         c.count2();
00028         while(!m.tryLock()){
00029           for(int i=0;i<2;i++){
00030             if(!m.waitLock(100)) break;
00031             if(m.tryLock()) return;
00032           }
00033           c.count1();
00034           boost::thread::yield();
00035         }
00036       }
00037 #else
00038       LightScopedLock(Mutex& m) :m(m){
00039         m.lock();
00040       }
00041 #endif
00042       ~LightScopedLock(){
00043         m.unlock();
00044       }
00045     };
00046 
00047 
00048     class LightMutex : boost::noncopyable {
00049       volatile int data;
00050     public:
00051       typedef LightScopedLock<LightMutex> scoped_lock;
00052       class unlockable_lock;
00053       LightMutex() :data(0) {}
00054       bool tryLock(){
00055         if(data!=0) return false;
00056         int dummy;
00057 #ifdef __GNUC__
00058         asm __volatile__(" movl $1,%0" "\n\t"
00059                          " xchgl (%1),%0" "\n\t"
00060                          : "=&q"(dummy)
00061                          : "q"(&data)
00062                          : "cc");
00063 #else
00064 #  error "not supported"
00065 #endif
00066         return dummy==0;
00067       }
00068       bool waitLock(int counter){
00069         for(int i=0;i<counter;i++){
00070 #ifdef __GNUC__
00071           asm __volatile__(" pause" "\n\t");
00072 #endif
00073           if(data==0)
00074             return true;
00075         }
00076         return false;
00077       }
00078       void lock(){
00079         while(!tryLock()){
00080           for(int i=0;i<2;i++){
00081             if(!waitLock(100)) break;
00082             if(tryLock()) return;
00083           }
00084           boost::thread::yield();
00085         }
00086       }
00087       void unlock(){
00088         data=0;
00089       }
00090     };
00091     
00093     class LightMutex::unlockable_lock : boost::noncopyable {
00094       LightMutex& m;
00095       bool locked;
00096     public:
00097       unlockable_lock(LightMutex& m) :m(m), locked(true) {
00098         m.lock();
00099       }
00100       ~unlockable_lock(){
00101         unlock();
00102       }
00103       void unlock()
00104       {
00105         if (locked) {
00106           locked = false;
00107           m.unlock();
00108         }
00109       }
00110     };
00111 
00112     class LightMutexChar : boost::noncopyable {
00113       volatile char data;
00114     public:
00115       typedef LightScopedLock<LightMutexChar> scoped_lock;
00116       LightMutexChar() :data(0) {}
00117       bool tryLock(){
00118         if(data!=0) return false;
00119         char dummy;
00120 #ifdef __GNUC__
00121         asm __volatile__(" movb $1,%0" "\n\t"
00122                          " xchgb (%1),%0" "\n\t"
00123                          : "=&q"(dummy)
00124                          : "q"(&data)
00125                          : "cc");
00126 #else
00127 #  error "not supported"
00128 #endif
00129         return dummy==0;
00130       }
00131       bool waitLock(int counter){
00132         for(int i=0;i<counter;i++){
00133 #ifdef __GNUC__
00134           asm __volatile__(" pause" "\n\t");
00135 #endif
00136           if(data==0)
00137             return true;
00138         }
00139         return false;
00140       }
00141       void lock(){
00142         while(!tryLock()){
00143           for(int i=0;i<2;i++){
00144             if(!waitLock(100)) break;
00145             if(tryLock()) return;
00146           }
00147           boost::thread::yield();
00148         }
00149       }
00150       void unlock(){
00151         data=0;
00152       }
00153     };
00154 #endif
00155 
00156 #ifdef PROFILE_MUTEX
00157 #  define SCOPED_LOCK(lock,m) \
00158     static osl::misc::CounterPair c(__FILE__, __FUNCTION__, __LINE__);  \
00159     osl::misc::LightMutex::scoped_lock lock(c,m);
00160 #  define SCOPED_LOCK_CHAR(lock,m) \
00161     static osl::misc::CounterPair c(__FILE__, __FUNCTION__, __LINE__);  \
00162     osl::misc::LightMutexChar::scoped_lock lock(c,m);
00163 #else
00164 #  define SCOPED_LOCK(lock,m) \
00165     osl::misc::LightMutex::scoped_lock lock(m);
00166 #  define SCOPED_LOCK_CHAR(lock,m) \
00167     osl::misc::LightMutexChar::scoped_lock lock(m);
00168 #endif
00169   }
00170   using misc::LightMutex;
00171 }
00172 #endif /* OSL_LIGHT_MUTEX_H */
00173 // ;;; Local Variables:
00174 // ;;; mode:c++
00175 // ;;; c-basic-offset:2
00176 // ;;; End:
00177 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines