00001
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
00173
00174
00175
00176
00177