TinyThread++ 1.1
|
00001 /* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- 00002 Copyright (c) 2010-2012 Marcus Geelnard 00003 00004 This software is provided 'as-is', without any express or implied 00005 warranty. In no event will the authors be held liable for any damages 00006 arising from the use of this software. 00007 00008 Permission is granted to anyone to use this software for any purpose, 00009 including commercial applications, and to alter it and redistribute it 00010 freely, subject to the following restrictions: 00011 00012 1. The origin of this software must not be misrepresented; you must not 00013 claim that you wrote the original software. If you use this software 00014 in a product, an acknowledgment in the product documentation would be 00015 appreciated but is not required. 00016 00017 2. Altered source versions must be plainly marked as such, and must not be 00018 misrepresented as being the original software. 00019 00020 3. This notice may not be removed or altered from any source 00021 distribution. 00022 */ 00023 00024 #ifndef _FAST_MUTEX_H_ 00025 #define _FAST_MUTEX_H_ 00026 00028 00029 // Which platform are we on? 00030 #if !defined(_TTHREAD_PLATFORM_DEFINED_) 00031 #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) 00032 #define _TTHREAD_WIN32_ 00033 #else 00034 #define _TTHREAD_POSIX_ 00035 #endif 00036 #define _TTHREAD_PLATFORM_DEFINED_ 00037 #endif 00038 00039 // Check if we can support the assembly language level implementation (otherwise 00040 // revert to the system API) 00041 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || \ 00042 (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) || \ 00043 (defined(__GNUC__) && (defined(__ppc__))) 00044 #define _FAST_MUTEX_ASM_ 00045 #else 00046 #define _FAST_MUTEX_SYS_ 00047 #endif 00048 00049 #if defined(_TTHREAD_WIN32_) 00050 #ifndef WIN32_LEAN_AND_MEAN 00051 #define WIN32_LEAN_AND_MEAN 00052 #define __UNDEF_LEAN_AND_MEAN 00053 #endif 00054 #include <windows.h> 00055 #ifdef __UNDEF_LEAN_AND_MEAN 00056 #undef WIN32_LEAN_AND_MEAN 00057 #undef __UNDEF_LEAN_AND_MEAN 00058 #endif 00059 #else 00060 #ifdef _FAST_MUTEX_ASM_ 00061 #include <sched.h> 00062 #else 00063 #include <pthread.h> 00064 #endif 00065 #endif 00066 00067 namespace tthread { 00068 00088 class fast_mutex { 00089 public: 00091 #if defined(_FAST_MUTEX_ASM_) 00092 fast_mutex() : mLock(0) {} 00093 #else 00094 fast_mutex() 00095 { 00096 #if defined(_TTHREAD_WIN32_) 00097 InitializeCriticalSection(&mHandle); 00098 #elif defined(_TTHREAD_POSIX_) 00099 pthread_mutex_init(&mHandle, NULL); 00100 #endif 00101 } 00102 #endif 00103 00104 #if !defined(_FAST_MUTEX_ASM_) 00105 00106 ~fast_mutex() 00107 { 00108 #if defined(_TTHREAD_WIN32_) 00109 DeleteCriticalSection(&mHandle); 00110 #elif defined(_TTHREAD_POSIX_) 00111 pthread_mutex_destroy(&mHandle); 00112 #endif 00113 } 00114 #endif 00115 00120 inline void lock() 00121 { 00122 #if defined(_FAST_MUTEX_ASM_) 00123 bool gotLock; 00124 do { 00125 gotLock = try_lock(); 00126 if(!gotLock) 00127 { 00128 #if defined(_TTHREAD_WIN32_) 00129 Sleep(0); 00130 #elif defined(_TTHREAD_POSIX_) 00131 sched_yield(); 00132 #endif 00133 } 00134 } while(!gotLock); 00135 #else 00136 #if defined(_TTHREAD_WIN32_) 00137 EnterCriticalSection(&mHandle); 00138 #elif defined(_TTHREAD_POSIX_) 00139 pthread_mutex_lock(&mHandle); 00140 #endif 00141 #endif 00142 } 00143 00149 inline bool try_lock() 00150 { 00151 #if defined(_FAST_MUTEX_ASM_) 00152 int oldLock; 00153 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) 00154 asm volatile ( 00155 "movl $1,%%eax\n\t" 00156 "xchg %%eax,%0\n\t" 00157 "movl %%eax,%1\n\t" 00158 : "=m" (mLock), "=m" (oldLock) 00159 : 00160 : "%eax", "memory" 00161 ); 00162 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) 00163 int *ptrLock = &mLock; 00164 __asm { 00165 mov eax,1 00166 mov ecx,ptrLock 00167 xchg eax,[ecx] 00168 mov oldLock,eax 00169 } 00170 #elif defined(__GNUC__) && (defined(__ppc__)) 00171 int newLock = 1; 00172 asm volatile ( 00173 "\n1:\n\t" 00174 "lwarx %0,0,%1\n\t" 00175 "cmpwi 0,%0,0\n\t" 00176 "bne- 2f\n\t" 00177 "stwcx. %2,0,%1\n\t" 00178 "bne- 1b\n\t" 00179 "isync\n" 00180 "2:\n\t" 00181 : "=&r" (oldLock) 00182 : "r" (&mLock), "r" (newLock) 00183 : "cr0", "memory" 00184 ); 00185 #endif 00186 return (oldLock == 0); 00187 #else 00188 #if defined(_TTHREAD_WIN32_) 00189 return TryEnterCriticalSection(&mHandle) ? true : false; 00190 #elif defined(_TTHREAD_POSIX_) 00191 return (pthread_mutex_trylock(&mHandle) == 0) ? true : false; 00192 #endif 00193 #endif 00194 } 00195 00199 inline void unlock() 00200 { 00201 #if defined(_FAST_MUTEX_ASM_) 00202 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) 00203 asm volatile ( 00204 "movl $0,%%eax\n\t" 00205 "xchg %%eax,%0\n\t" 00206 : "=m" (mLock) 00207 : 00208 : "%eax", "memory" 00209 ); 00210 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) 00211 int *ptrLock = &mLock; 00212 __asm { 00213 mov eax,0 00214 mov ecx,ptrLock 00215 xchg eax,[ecx] 00216 } 00217 #elif defined(__GNUC__) && (defined(__ppc__)) 00218 asm volatile ( 00219 "sync\n\t" // Replace with lwsync where possible? 00220 : : : "memory" 00221 ); 00222 mLock = 0; 00223 #endif 00224 #else 00225 #if defined(_TTHREAD_WIN32_) 00226 LeaveCriticalSection(&mHandle); 00227 #elif defined(_TTHREAD_POSIX_) 00228 pthread_mutex_unlock(&mHandle); 00229 #endif 00230 #endif 00231 } 00232 00233 private: 00234 #if defined(_FAST_MUTEX_ASM_) 00235 int mLock; 00236 #else 00237 #if defined(_TTHREAD_WIN32_) 00238 CRITICAL_SECTION mHandle; 00239 #elif defined(_TTHREAD_POSIX_) 00240 pthread_mutex_t mHandle; 00241 #endif 00242 #endif 00243 }; 00244 00245 } 00246 00247 #endif // _FAST_MUTEX_H_ 00248