fast_mutex.h
上传用户:sunlush021
上传日期:2022-06-22
资源大小:90k
文件大小:6k
源码类别:

操作系统开发

开发平台:

C/C++

  1. /*
  2. Copyright (c) 2010 Marcus Geelnard
  3. This software is provided 'as-is', without any express or implied
  4. warranty. In no event will the authors be held liable for any damages
  5. arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it
  8. freely, subject to the following restrictions:
  9.     1. The origin of this software must not be misrepresented; you must not
  10.     claim that you wrote the original software. If you use this software
  11.     in a product, an acknowledgment in the product documentation would be
  12.     appreciated but is not required.
  13.     2. Altered source versions must be plainly marked as such, and must not be
  14.     misrepresented as being the original software.
  15.     3. This notice may not be removed or altered from any source
  16.     distribution.
  17. */
  18. #ifndef _FAST_MUTEX_H_
  19. #define _FAST_MUTEX_H_
  20. // Which platform are we on?
  21. #if !defined(_TTHREAD_PLATFORM_DEFINED_)
  22.   #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
  23.     #define _TTHREAD_WIN32_
  24.   #else
  25.     #define _TTHREAD_POSIX_
  26.   #endif
  27.   #define _TTHREAD_PLATFORM_DEFINED_
  28. #endif
  29. // Check if we can support the assembly language level implementation (otherwise
  30. // revert to the system API)
  31. #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || 
  32.     (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) || 
  33.     (defined(__GNUC__) && (defined(__ppc__)))
  34.   #define _FAST_MUTEX_ASM_
  35. #else
  36.   #define _FAST_MUTEX_SYS_
  37. #endif
  38. #if defined(_TTHREAD_WIN32_)
  39.   #include <windows.h>
  40. #else
  41.   #ifdef _FAST_MUTEX_ASM_
  42.     #include <sched.h>
  43.   #else
  44.     #include <pthread.h>
  45.   #endif
  46. #endif
  47. namespace tthread {
  48. /// Fast mutex class.
  49. /// This is a mutual exclusion object for synchronizing access to shared
  50. /// memory areas for several threads. It is similar to the tthread::mutex class,
  51. /// but instead of using system level functions, it is implemented as an atomic
  52. /// spin lock with very low CPU overhead when possible.
  53. ///
  54. /// The c fast_mutex class is NOT compatible with the c condition_variable
  55. /// class (however, it IS compatible with the c lock_guard class). It should
  56. /// also be noted that the c fast_mutex class typically does not provide
  57. /// as accurate thread scheduling as a the standard c mutex class does.
  58. ///
  59. /// Because of the limitations of the class, it should only be used in
  60. /// situations where the mutex needs to be locked/unlocked very frequently.
  61. ///
  62. /// @note The "fast" version of this class relies on inline assembler language,
  63. /// which is currently only supported for 32/64-bit Intel x86/AMD64 and
  64. /// PowerPC architectures on a limited number of compilers (GNU g++ and MS
  65. /// Visual C++).
  66. /// For other architectures/compilers, system functions are used instead.
  67. class fast_mutex {
  68.   public:
  69.     /// Constructor.
  70. #if defined(_FAST_MUTEX_ASM_)
  71.     fast_mutex() : mLock(0) {}
  72. #else
  73.     fast_mutex()
  74.     {
  75.   #if defined(_TTHREAD_WIN32_)
  76.       InitializeCriticalSection(&mHandle);
  77.   #else
  78.       pthread_mutex_init(&mHandle, NULL);
  79.   #endif
  80.     }
  81. #endif
  82.     /// Destructor.
  83.     ~fast_mutex()
  84.     {
  85. #if !defined(_FAST_MUTEX_ASM_)
  86.   #if defined(_TTHREAD_WIN32_)
  87.       DeleteCriticalSection(&mHandle);
  88.   #else
  89.       pthread_mutex_destroy(&mHandle);
  90.   #endif
  91. #endif
  92.     }
  93.     /// Lock the mutex.
  94.     /// The method will block the calling thread until a lock on the mutex can
  95.     /// be obtained. The mutex remains locked until c unlock() is called.
  96.     /// @see lock_guard
  97.     inline void lock()
  98.     {
  99. #if defined(_FAST_MUTEX_ASM_)
  100.       bool gotLock;
  101.       do {
  102.         gotLock = try_lock();
  103.         if(!gotLock)
  104.   #if defined(_TTHREAD_WIN32_)
  105.           Sleep(0);
  106.   #else
  107.           sched_yield();
  108.   #endif
  109.       } while(!gotLock);
  110. #else
  111.   #if defined(_TTHREAD_WIN32_)
  112.       EnterCriticalSection(&mHandle);
  113.   #else
  114.       pthread_mutex_lock(&mHandle);
  115.   #endif
  116. #endif
  117.     }
  118.     /// Try to lock the mutex.
  119.     /// The method will try to lock the mutex. If it fails, the function will
  120.     /// return immediately (non-blocking).
  121.     /// @return c true if the lock was acquired, or c false if the lock could
  122.     /// not be acquired.
  123.     inline bool try_lock()
  124.     {
  125. #if defined(_FAST_MUTEX_ASM_)
  126.       int oldLock;
  127.   #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
  128.       asm volatile (
  129.         "movl $1,%%eaxnt"
  130.         "xchg %%eax,%0nt"
  131.         "movl %%eax,%1nt"
  132.         : "=m" (mLock), "=m" (oldLock)
  133.         :
  134.         : "%eax", "memory"
  135.       );
  136.   #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
  137.       int *ptrLock = &mLock;
  138.       __asm {
  139.         mov eax,1
  140.         mov ecx,ptrLock
  141.         xchg eax,[ecx]
  142.         mov oldLock,eax
  143.       }
  144.   #elif defined(__GNUC__) && (defined(__ppc__))
  145.       int newLock = 1;
  146.       asm volatile (
  147.         "n1:nt"
  148.         "lwarx  %0,0,%1nt"
  149.         "cmpwi  0,%0,0nt"
  150.         "bne-   2fnt"
  151.         "stwcx. %2,0,%1nt"
  152.         "bne-   1bnt"
  153.         "isyncn"
  154.         "2:nt"
  155.         : "=&r" (oldLock)
  156.         : "r" (&mLock), "r" (newLock)
  157.         : "cr0", "memory"
  158.       );
  159.   #endif
  160.       return (oldLock == 0);
  161. #else
  162.   #if defined(_TTHREAD_WIN32_)
  163.       return TryEnterCriticalSection(&mHandle) ? true : false;
  164.   #else
  165.       return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
  166.   #endif
  167. #endif
  168.     }
  169.     /// Unlock the mutex.
  170.     /// If any threads are waiting for the lock on this mutex, one of them will
  171.     /// be unblocked.
  172.     inline void unlock()
  173.     {
  174. #if defined(_FAST_MUTEX_ASM_)
  175.   #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
  176.       asm volatile (
  177.         "movl $0,%%eaxnt"
  178.         "xchg %%eax,%0nt"
  179.         : "=m" (mLock)
  180.         :
  181.         : "%eax", "memory"
  182.       );
  183.   #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
  184.       int *ptrLock = &mLock;
  185.       __asm {
  186.         mov eax,0
  187.         mov ecx,ptrLock
  188.         xchg eax,[ecx]
  189.       }
  190.   #elif defined(__GNUC__) && (defined(__ppc__))
  191.       asm volatile (
  192.         "syncnt"  // Replace with lwsync where possible?
  193.         : : : "memory"
  194.       );
  195.       mLock = 0;
  196.   #endif
  197. #else
  198.   #if defined(_TTHREAD_WIN32_)
  199.       LeaveCriticalSection(&mHandle);
  200.   #else
  201.       pthread_mutex_unlock(&mHandle);
  202.   #endif
  203. #endif
  204.     }
  205.   private:
  206. #if defined(_FAST_MUTEX_ASM_)
  207.     int mLock;
  208. #else
  209.   #if defined(_TTHREAD_WIN32_)
  210.     CRITICAL_SECTION mHandle;
  211.   #else
  212.     pthread_mutex_t mHandle;
  213.   #endif
  214. #endif
  215. };
  216. }
  217. #endif // _FAST_MUTEX_H_