fast_mutex.h
上传用户:sunlush021
上传日期:2022-06-22
资源大小:90k
文件大小:6k
- /*
- Copyright (c) 2010 Marcus Geelnard
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source
- distribution.
- */
- #ifndef _FAST_MUTEX_H_
- #define _FAST_MUTEX_H_
- // Which platform are we on?
- #if !defined(_TTHREAD_PLATFORM_DEFINED_)
- #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
- #define _TTHREAD_WIN32_
- #else
- #define _TTHREAD_POSIX_
- #endif
- #define _TTHREAD_PLATFORM_DEFINED_
- #endif
- // Check if we can support the assembly language level implementation (otherwise
- // revert to the system API)
- #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) ||
- (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) ||
- (defined(__GNUC__) && (defined(__ppc__)))
- #define _FAST_MUTEX_ASM_
- #else
- #define _FAST_MUTEX_SYS_
- #endif
- #if defined(_TTHREAD_WIN32_)
- #include <windows.h>
- #else
- #ifdef _FAST_MUTEX_ASM_
- #include <sched.h>
- #else
- #include <pthread.h>
- #endif
- #endif
- namespace tthread {
- /// Fast mutex class.
- /// This is a mutual exclusion object for synchronizing access to shared
- /// memory areas for several threads. It is similar to the tthread::mutex class,
- /// but instead of using system level functions, it is implemented as an atomic
- /// spin lock with very low CPU overhead when possible.
- ///
- /// The c fast_mutex class is NOT compatible with the c condition_variable
- /// class (however, it IS compatible with the c lock_guard class). It should
- /// also be noted that the c fast_mutex class typically does not provide
- /// as accurate thread scheduling as a the standard c mutex class does.
- ///
- /// Because of the limitations of the class, it should only be used in
- /// situations where the mutex needs to be locked/unlocked very frequently.
- ///
- /// @note The "fast" version of this class relies on inline assembler language,
- /// which is currently only supported for 32/64-bit Intel x86/AMD64 and
- /// PowerPC architectures on a limited number of compilers (GNU g++ and MS
- /// Visual C++).
- /// For other architectures/compilers, system functions are used instead.
- class fast_mutex {
- public:
- /// Constructor.
- #if defined(_FAST_MUTEX_ASM_)
- fast_mutex() : mLock(0) {}
- #else
- fast_mutex()
- {
- #if defined(_TTHREAD_WIN32_)
- InitializeCriticalSection(&mHandle);
- #else
- pthread_mutex_init(&mHandle, NULL);
- #endif
- }
- #endif
- /// Destructor.
- ~fast_mutex()
- {
- #if !defined(_FAST_MUTEX_ASM_)
- #if defined(_TTHREAD_WIN32_)
- DeleteCriticalSection(&mHandle);
- #else
- pthread_mutex_destroy(&mHandle);
- #endif
- #endif
- }
- /// Lock the mutex.
- /// The method will block the calling thread until a lock on the mutex can
- /// be obtained. The mutex remains locked until c unlock() is called.
- /// @see lock_guard
- inline void lock()
- {
- #if defined(_FAST_MUTEX_ASM_)
- bool gotLock;
- do {
- gotLock = try_lock();
- if(!gotLock)
- #if defined(_TTHREAD_WIN32_)
- Sleep(0);
- #else
- sched_yield();
- #endif
- } while(!gotLock);
- #else
- #if defined(_TTHREAD_WIN32_)
- EnterCriticalSection(&mHandle);
- #else
- pthread_mutex_lock(&mHandle);
- #endif
- #endif
- }
- /// Try to lock the mutex.
- /// The method will try to lock the mutex. If it fails, the function will
- /// return immediately (non-blocking).
- /// @return c true if the lock was acquired, or c false if the lock could
- /// not be acquired.
- inline bool try_lock()
- {
- #if defined(_FAST_MUTEX_ASM_)
- int oldLock;
- #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
- asm volatile (
- "movl $1,%%eaxnt"
- "xchg %%eax,%0nt"
- "movl %%eax,%1nt"
- : "=m" (mLock), "=m" (oldLock)
- :
- : "%eax", "memory"
- );
- #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
- int *ptrLock = &mLock;
- __asm {
- mov eax,1
- mov ecx,ptrLock
- xchg eax,[ecx]
- mov oldLock,eax
- }
- #elif defined(__GNUC__) && (defined(__ppc__))
- int newLock = 1;
- asm volatile (
- "n1:nt"
- "lwarx %0,0,%1nt"
- "cmpwi 0,%0,0nt"
- "bne- 2fnt"
- "stwcx. %2,0,%1nt"
- "bne- 1bnt"
- "isyncn"
- "2:nt"
- : "=&r" (oldLock)
- : "r" (&mLock), "r" (newLock)
- : "cr0", "memory"
- );
- #endif
- return (oldLock == 0);
- #else
- #if defined(_TTHREAD_WIN32_)
- return TryEnterCriticalSection(&mHandle) ? true : false;
- #else
- return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
- #endif
- #endif
- }
- /// Unlock the mutex.
- /// If any threads are waiting for the lock on this mutex, one of them will
- /// be unblocked.
- inline void unlock()
- {
- #if defined(_FAST_MUTEX_ASM_)
- #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
- asm volatile (
- "movl $0,%%eaxnt"
- "xchg %%eax,%0nt"
- : "=m" (mLock)
- :
- : "%eax", "memory"
- );
- #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
- int *ptrLock = &mLock;
- __asm {
- mov eax,0
- mov ecx,ptrLock
- xchg eax,[ecx]
- }
- #elif defined(__GNUC__) && (defined(__ppc__))
- asm volatile (
- "syncnt" // Replace with lwsync where possible?
- : : : "memory"
- );
- mLock = 0;
- #endif
- #else
- #if defined(_TTHREAD_WIN32_)
- LeaveCriticalSection(&mHandle);
- #else
- pthread_mutex_unlock(&mHandle);
- #endif
- #endif
- }
- private:
- #if defined(_FAST_MUTEX_ASM_)
- int mLock;
- #else
- #if defined(_TTHREAD_WIN32_)
- CRITICAL_SECTION mHandle;
- #else
- pthread_mutex_t mHandle;
- #endif
- #endif
- };
- }
- #endif // _FAST_MUTEX_H_