TinyThread++: fast_mutex.h Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# fast_mutex.h

Go to the documentation of this file.

    00001 /*
    00002 Copyright (c) 2010 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   #include <windows.h>
    00051 #else
    00052   #ifdef _FAST_MUTEX_ASM_
    00053     #include <sched.h>
    00054   #else
    00055     #include <pthread.h>
    00056   #endif
    00057 #endif
    00058
    00059 namespace tthread {
    00060
    00080 class fast_mutex {
    00081   public:
    00083 #if defined(_FAST_MUTEX_ASM_)
    00084     fast_mutex() : mLock(0) {}
    00085 #else
    00086     fast_mutex()
    00087     {
    00088   #if defined(_TTHREAD_WIN32_)
    00089       InitializeCriticalSection(&mHandle);
    00090   #elif defined(_TTHREAD_POSIX_)
    00091       pthread_mutex_init(&mHandle, NULL);
    00092   #endif
    00093     }
    00094 #endif
    00095
    00096 #if !defined(_FAST_MUTEX_ASM_)
    00097
    00098     ~fast_mutex()
    00099     {
    00100   #if defined(_TTHREAD_WIN32_)
    00101       DeleteCriticalSection(&mHandle);
    00102   #elif defined(_TTHREAD_POSIX_)
    00103       pthread_mutex_destroy(&mHandle);
    00104   #endif
    00105     }
    00106 #endif
    00107
    00112     inline void lock()
    00113     {
    00114 #if defined(_FAST_MUTEX_ASM_)
    00115       bool gotLock;
    00116       do {
    00117         gotLock = try_lock();
    00118         if(!gotLock)
    00119         {
    00120   #if defined(_TTHREAD_WIN32_)
    00121           Sleep(0);
    00122   #elif defined(_TTHREAD_POSIX_)
    00123           sched_yield();
    00124   #endif
    00125         }
    00126       } while(!gotLock);
    00127 #else
    00128   #if defined(_TTHREAD_WIN32_)
    00129       EnterCriticalSection(&mHandle);
    00130   #elif defined(_TTHREAD_POSIX_)
    00131       pthread_mutex_lock(&mHandle);
    00132   #endif
    00133 #endif
    00134     }
    00135
    00141     inline bool try_lock()
    00142     {
    00143 #if defined(_FAST_MUTEX_ASM_)
    00144       int oldLock;
    00145   #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
    00146       asm volatile (
    00147         "movl $1,%%eax\n\t"
    00148         "xchg %%eax,%0\n\t"
    00149         "movl %%eax,%1\n\t"
    00150         : "=m" (mLock), "=m" (oldLock)
    00151         :
    00152         : "%eax", "memory"
    00153       );
    00154   #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
    00155       int *ptrLock = &mLock;
    00156       __asm {
    00157         mov eax,1
    00158         mov ecx,ptrLock
    00159         xchg eax,[ecx]
    00160         mov oldLock,eax
    00161       }
    00162   #elif defined(__GNUC__) && (defined(__ppc__))
    00163       int newLock = 1;
    00164       asm volatile (
    00165         "\n1:\n\t"
    00166         "lwarx  %0,0,%1\n\t"
    00167         "cmpwi  0,%0,0\n\t"
    00168         "bne-   2f\n\t"
    00169         "stwcx. %2,0,%1\n\t"
    00170         "bne-   1b\n\t"
    00171         "isync\n"
    00172         "2:\n\t"
    00173         : "=&r" (oldLock)
    00174         : "r" (&mLock), "r" (newLock)
    00175         : "cr0", "memory"
    00176       );
    00177   #endif
    00178       return (oldLock == 0);
    00179 #else
    00180   #if defined(_TTHREAD_WIN32_)
    00181       return TryEnterCriticalSection(&mHandle) ? true : false;
    00182   #elif defined(_TTHREAD_POSIX_)
    00183       return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
    00184   #endif
    00185 #endif
    00186     }
    00187
    00191     inline void unlock()
    00192     {
    00193 #if defined(_FAST_MUTEX_ASM_)
    00194   #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
    00195       asm volatile (
    00196         "movl $0,%%eax\n\t"
    00197         "xchg %%eax,%0\n\t"
    00198         : "=m" (mLock)
    00199         :
    00200         : "%eax", "memory"
    00201       );
    00202   #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
    00203       int *ptrLock = &mLock;
    00204       __asm {
    00205         mov eax,0
    00206         mov ecx,ptrLock
    00207         xchg eax,[ecx]
    00208       }
    00209   #elif defined(__GNUC__) && (defined(__ppc__))
    00210       asm volatile (
    00211         "sync\n\t"  // Replace with lwsync where possible?
    00212         : : : "memory"
    00213       );
    00214       mLock = 0;
    00215   #endif
    00216 #else
    00217   #if defined(_TTHREAD_WIN32_)
    00218       LeaveCriticalSection(&mHandle);
    00219   #elif defined(_TTHREAD_POSIX_)
    00220       pthread_mutex_unlock(&mHandle);
    00221   #endif
    00222 #endif
    00223     }
    00224
    00225   private:
    00226 #if defined(_FAST_MUTEX_ASM_)
    00227     int mLock;
    00228 #else
    00229   #if defined(_TTHREAD_WIN32_)
    00230     CRITICAL_SECTION mHandle;
    00231   #elif defined(_TTHREAD_POSIX_)
    00232     pthread_mutex_t mHandle;
    00233   #endif
    00234 #endif
    00235 };
    00236
    00237 }
    00238
    00239 #endif // _FAST_MUTEX_H_