hmutex.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #ifndef HV_MUTEX_H_
  2. #define HV_MUTEX_H_
  3. #include "hplatform.h"
  4. #ifdef _MSC_VER
  5. #define hmutex_t CRITICAL_SECTION
  6. #define hmutex_init InitializeCriticalSection
  7. #define hmutex_destroy DeleteCriticalSection
  8. #define hmutex_lock EnterCriticalSection
  9. #define hmutex_unlock LeaveCriticalSection
  10. #define HSPINLOCK_COUNT -1
  11. #define hspinlock_t CRITICAL_SECTION
  12. #define hspinlock_init(pspin) InitializeCriticalSectionAndSpinCount(pspin, HSPINLOCK_COUNT)
  13. #define hspinlock_destroy DeleteCriticalSection
  14. #define hspinlock_lock EnterCriticalSection
  15. #define hspinlock_unlock LeaveCriticalSection
  16. #define hrwlock_t SRWLOCK
  17. #define hrwlock_init InitializeSRWLock
  18. #define hrwlock_destroy
  19. #define hrwlock_rdlock AcquireSRWLockShared
  20. #define hrwlock_rdunlock ReleaseSRWLockShared
  21. #define hrwlock_wrlock AcquireSRWLockExclusive
  22. #define hrwlock_wrunlock ReleaseSRWLockExclusive
  23. #define htimed_mutex_t HANDLE
  24. #define htimed_mutex_init(pmutex) *(pmutex) = CreateMutex(NULL, FALSE, NULL)
  25. #define htimed_mutex_destroy(pmutex) CloseHandle(*(pmutex))
  26. #define htimed_mutex_lock(pmutex) WaitForSingleObject(*(pmutex), INFINITE)
  27. #define htimed_mutex_unlock(pmutex) ReleaseMutex(*(pmutex))
  28. // true: WAIT_OBJECT_0
  29. // false: WAIT_OBJECT_TIMEOUT
  30. #define htimed_mutex_lock_for(pmutex, ms) ( WaitForSingleObject(*(pmutex), ms) == WAIT_OBJECT_0 )
  31. #define hcondvar_t CONDITION_VARIABLE
  32. #define hcondvar_init InitializeConditionVariable
  33. #define hcondvar_destroy
  34. #define hcondvar_wait(pcond, pmutex) SleepConditionVariableCS(pcond, pmutex, INFINITE)
  35. #define hcondvar_wait_for(pcond, pmutex, ms) SleepConditionVariableCS(pcond, pmutex, ms)
  36. #define hcondvar_signal WakeConditionVariable
  37. #define hcondvar_broadcast WakeAllConditionVariable
  38. #define honce_t INIT_ONCE
  39. #define HONCE_INIT INIT_ONCE_STATIC_INIT
  40. typedef void (*honce_fn)();
  41. static inline BOOL WINAPI s_once_func(INIT_ONCE* once, PVOID arg, PVOID* _) {
  42. honce_fn fn = (honce_fn)arg;
  43. fn();
  44. return TRUE;
  45. }
  46. static inline void honce(honce_t* once, honce_fn fn) {
  47. PVOID dummy = NULL;
  48. InitOnceExecuteOnce(once, s_once_func, (PVOID)fn, &dummy);
  49. }
  50. #else
  51. #define hmutex_t pthread_mutex_t
  52. #define hmutex_init(pmutex) pthread_mutex_init(pmutex, NULL)
  53. #define hmutex_destroy pthread_mutex_destroy
  54. #define hmutex_lock pthread_mutex_lock
  55. #define hmutex_unlock pthread_mutex_unlock
  56. #if HAVE_PTHREAD_SPIN_LOCK
  57. #define hspinlock_t pthread_spinlock_t
  58. #define hspinlock_init(pspin) pthread_spin_init(pspin, PTHREAD_PROCESS_PRIVATE)
  59. #define hspinlock_destroy pthread_spin_destroy
  60. #define hspinlock_lock pthread_spin_lock
  61. #define hspinlock_unlock pthread_spin_unlock
  62. #endif
  63. #define hrwlock_t pthread_rwlock_t
  64. #define hrwlock_init(prwlock) pthread_rwlock_init(prwlock, NULL)
  65. #define hrwlock_destroy pthread_rwlock_destroy
  66. #define hrwlock_rdlock pthread_rwlock_rdlock
  67. #define hrwlock_rdunlock pthread_rwlock_unlock
  68. #define hrwlock_wrlock pthread_rwlock_wrlock
  69. #define hrwlock_wrunlock pthread_rwlock_unlock
  70. #if HAVE_PTHREAD_MUTEX_TIMEDLOCK
  71. #define htimed_mutex_t pthread_mutex_t
  72. #define htimed_mutex_init(pmutex) pthread_mutex_init(pmutex, NULL)
  73. #define htimed_mutex_destroy pthread_mutex_destroy
  74. #define htimed_mutex_lock pthread_mutex_lock
  75. #define htimed_mutex_unlock pthread_mutex_unlock
  76. // true: OK
  77. // false: ETIMEDOUT
  78. static inline int htimed_mutex_lock_for(htimed_mutex_t* mutex, unsigned long ms) {
  79. struct timespec ts;
  80. struct timeval tv;
  81. gettimeofday(&tv, NULL);
  82. ts.tv_sec = tv.tv_sec + ms / 1000;
  83. ts.tv_nsec = tv.tv_usec * 1000 + ms % 1000 * 1000000;
  84. if (ts.tv_nsec >= 1000000000) {
  85. ts.tv_nsec -= 1000000000;
  86. ts.tv_sec += 1;
  87. }
  88. return pthread_mutex_timedlock(mutex, &ts) != ETIMEDOUT;
  89. }
  90. #endif
  91. #define hcondvar_t pthread_cond_t
  92. #define hcondvar_init(pcond) pthread_cond_init(pcond, NULL)
  93. #define hcondvar_destroy pthread_cond_destroy
  94. #define hcondvar_wait pthread_cond_wait
  95. // true: OK
  96. // false: ETIMEDOUT
  97. static inline int hcondvar_wait_for(hcondvar_t* cond, hmutex_t* mutex, unsigned long ms) {
  98. struct timespec ts;
  99. struct timeval tv;
  100. gettimeofday(&tv, NULL);
  101. ts.tv_sec = tv.tv_sec + ms / 1000;
  102. ts.tv_nsec = tv.tv_usec * 1000 + ms % 1000 * 1000000;
  103. if (ts.tv_nsec >= 1000000000) {
  104. ts.tv_nsec -= 1000000000;
  105. ts.tv_sec += 1;
  106. }
  107. return pthread_cond_timedwait(cond, mutex, &ts) != ETIMEDOUT;
  108. }
  109. #define hcondvar_signal pthread_cond_signal
  110. #define hcondvar_broadcast pthread_cond_broadcast
  111. #define honce_t pthread_once_t
  112. #define HONCE_INIT PTHREAD_ONCE_INIT
  113. #define honce pthread_once
  114. #endif
  115. #ifdef __cplusplus
  116. #include <mutex>
  117. #include <condition_variable>
  118. using std::mutex;
  119. // NOTE: test std::timed_mutex incorrect in some platforms, use htimed_mutex_t
  120. // using std::timed_mutex;
  121. using std::condition_variable;
  122. using std::lock_guard;
  123. using std::unique_lock;
  124. class RWLock {
  125. public:
  126. RWLock() { hrwlock_init(&_rwlock); }
  127. ~RWLock() { hrwlock_destroy(&_rwlock); }
  128. void rdlock() { hrwlock_rdlock(&_rwlock); }
  129. void rdunlock() { hrwlock_rdunlock(&_rwlock); }
  130. void rwlock() { hrwlock_wrlock(&_rwlock); }
  131. void rwunlock() { hrwlock_wrunlock(&_rwlock); }
  132. protected:
  133. hrwlock_t _rwlock;
  134. };
  135. #endif
  136. #endif // HV_MUTEX_H_