説明を見る。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 <thread>
00011
00012
00013 namespace osl
00014 {
00015 namespace misc
00016 {
00017 #if defined OSL_USE_RACE_DETECTOR || defined _MSC_VER
00018 typedef std::mutex LightMutex;
00019 typedef std::mutex LightMutexChar;
00020 #else
00021 template <class Mutex>
00022 class LightScopedLock {
00023 LightScopedLock(const LightScopedLock&) = delete;
00024 LightScopedLock& operator=(const LightScopedLock&) = delete;
00025
00026 Mutex& m;
00027 public:
00028 #ifdef PROFILE_MUTEX
00029 LightScopedLock(osl::misc::CounterPair &c,Mutex& m) :m(m){
00030 c.count2();
00031 while(!m.tryLock()){
00032 for(int i=0;i<2;i++){
00033 if(!m.waitLock(100)) break;
00034 if(m.tryLock()) return;
00035 }
00036 c.count1();
00037 std::this_thread::yield();
00038 }
00039 }
00040 #else
00041 LightScopedLock(Mutex& m) :m(m){
00042 m.lock();
00043 }
00044 #endif
00045 ~LightScopedLock(){
00046 m.unlock();
00047 }
00048 };
00049
00050
00051 class LightMutex {
00052 LightMutex(const LightMutex&) = delete;
00053 LightMutex& operator=(const LightMutex&) = delete;
00054
00055 volatile int data;
00056 public:
00057 typedef LightScopedLock<LightMutex> scoped_lock;
00058 class unlockable_lock;
00059 LightMutex() :data(0) {}
00060 bool tryLock(){
00061 if(data!=0) return false;
00062 int dummy;
00063 #ifdef __GNUC__
00064 asm __volatile__(" movl $1,%0" "\n\t"
00065 " xchgl (%1),%0" "\n\t"
00066 : "=&q"(dummy)
00067 : "q"(&data)
00068 : "cc");
00069 #else
00070 # error "not supported"
00071 #endif
00072 return dummy==0;
00073 }
00074 bool waitLock(int counter){
00075 for(int i=0;i<counter;i++){
00076 #ifdef __GNUC__
00077 asm __volatile__(" pause" "\n\t");
00078 #endif
00079 if(data==0)
00080 return true;
00081 }
00082 return false;
00083 }
00084 void lock(){
00085 while(!tryLock()){
00086 for(int i=0;i<2;i++){
00087 if(!waitLock(100)) break;
00088 if(tryLock()) return;
00089 }
00090 std::this_thread::yield();
00091 }
00092 }
00093 void unlock(){
00094 data=0;
00095 }
00096 };
00097
00099 class LightMutex::unlockable_lock {
00100 unlockable_lock(const unlockable_lock&);
00101 unlockable_lock& operator=(const unlockable_lock&);
00102
00103 LightMutex& m;
00104 bool locked;
00105 public:
00106 unlockable_lock(LightMutex& m) :m(m), locked(true) {
00107 m.lock();
00108 }
00109 ~unlockable_lock(){
00110 unlock();
00111 }
00112 void unlock()
00113 {
00114 if (locked) {
00115 locked = false;
00116 m.unlock();
00117 }
00118 }
00119 };
00120
00121 class LightMutexChar {
00122 LightMutexChar(const LightMutexChar&) = delete;
00123 LightMutexChar& operator=(const LightMutexChar&) = delete;
00124
00125 volatile char data;
00126 public:
00127 typedef LightScopedLock<LightMutexChar> scoped_lock;
00128 LightMutexChar() :data(0) {}
00129 bool tryLock(){
00130 if(data!=0) return false;
00131 char dummy;
00132 #ifdef __GNUC__
00133 asm __volatile__(" movb $1,%0" "\n\t"
00134 " xchgb (%1),%0" "\n\t"
00135 : "=&q"(dummy)
00136 : "q"(&data)
00137 : "cc");
00138 #else
00139 # error "not supported"
00140 #endif
00141 return dummy==0;
00142 }
00143 bool waitLock(int counter){
00144 for(int i=0;i<counter;i++){
00145 #ifdef __GNUC__
00146 asm __volatile__(" pause" "\n\t");
00147 #endif
00148 if(data==0)
00149 return true;
00150 }
00151 return false;
00152 }
00153 void lock(){
00154 while(!tryLock()){
00155 for(int i=0;i<2;i++){
00156 if(!waitLock(100)) break;
00157 if(tryLock()) return;
00158 }
00159 std::this_thread::yield();
00160 }
00161 }
00162 void unlock(){
00163 data=0;
00164 }
00165 };
00166 #endif
00167
00168 #ifdef PROFILE_MUTEX
00169 # define SCOPED_LOCK(lock,m) \
00170 static osl::misc::CounterPair c(__FILE__, __FUNCTION__, __LINE__); \
00171 osl::misc::LightMutex::scoped_lock lock(c,m);
00172 # define SCOPED_LOCK_CHAR(lock,m) \
00173 static osl::misc::CounterPair c(__FILE__, __FUNCTION__, __LINE__); \
00174 osl::misc::LightMutexChar::scoped_lock lock(c,m);
00175 #else
00176 # define SCOPED_LOCK(lock,m) \
00177 osl::misc::LightMutex::scoped_lock lock(m);
00178 # define SCOPED_LOCK_CHAR(lock,m) \
00179 osl::misc::LightMutexChar::scoped_lock lock(m);
00180 #endif
00181 }
00182 using misc::LightMutex;
00183 }
00184 #endif
00185
00186
00187
00188
00189