std_mutex.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #pragma once
  2. #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
  3. #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
  4. #ifndef __has_include
  5. #define __has_include(s) 0
  6. #endif
  7. #if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
  8. // GCC 4.4 provides <mutex>
  9. #include <mutex>
  10. #elif __has_include(<mutex>) && !ANDROID
  11. // Clang + libc++
  12. #include <mutex>
  13. #else
  14. // partial <mutex> implementation for win32/pthread
  15. #include <algorithm>
  16. #if defined(_WIN32)
  17. // WIN32
  18. #define WIN32_LEAN_AND_MEAN
  19. #include <Windows.h>
  20. #else
  21. // POSIX
  22. #include <pthread.h>
  23. #endif
  24. #if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
  25. #define USE_RVALUE_REFERENCES
  26. #endif
  27. #if defined(_WIN32) && defined(_M_X64)
  28. #define USE_SRWLOCKS
  29. #endif
  30. namespace std
  31. {
  32. class recursive_mutex
  33. {
  34. #ifdef _WIN32
  35. typedef CRITICAL_SECTION native_type;
  36. #else
  37. typedef pthread_mutex_t native_type;
  38. #endif
  39. public:
  40. typedef native_type* native_handle_type;
  41. recursive_mutex(const recursive_mutex&) /*= delete*/;
  42. recursive_mutex& operator=(const recursive_mutex&) /*= delete*/;
  43. recursive_mutex()
  44. {
  45. #ifdef _WIN32
  46. InitializeCriticalSection(&m_handle);
  47. #else
  48. pthread_mutexattr_t attr;
  49. pthread_mutexattr_init(&attr);
  50. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  51. pthread_mutex_init(&m_handle, &attr);
  52. #endif
  53. }
  54. ~recursive_mutex()
  55. {
  56. #ifdef _WIN32
  57. DeleteCriticalSection(&m_handle);
  58. #else
  59. pthread_mutex_destroy(&m_handle);
  60. #endif
  61. }
  62. void lock()
  63. {
  64. #ifdef _WIN32
  65. EnterCriticalSection(&m_handle);
  66. #else
  67. pthread_mutex_lock(&m_handle);
  68. #endif
  69. }
  70. void unlock()
  71. {
  72. #ifdef _WIN32
  73. LeaveCriticalSection(&m_handle);
  74. #else
  75. pthread_mutex_unlock(&m_handle);
  76. #endif
  77. }
  78. bool try_lock()
  79. {
  80. #ifdef _WIN32
  81. return (0 != TryEnterCriticalSection(&m_handle));
  82. #else
  83. return !pthread_mutex_trylock(&m_handle);
  84. #endif
  85. }
  86. native_handle_type native_handle()
  87. {
  88. return &m_handle;
  89. }
  90. private:
  91. native_type m_handle;
  92. };
  93. #if !defined(_WIN32) || defined(USE_SRWLOCKS)
  94. class mutex
  95. {
  96. #ifdef _WIN32
  97. typedef SRWLOCK native_type;
  98. #else
  99. typedef pthread_mutex_t native_type;
  100. #endif
  101. public:
  102. typedef native_type* native_handle_type;
  103. mutex(const mutex&) /*= delete*/;
  104. mutex& operator=(const mutex&) /*= delete*/;
  105. mutex()
  106. {
  107. #ifdef _WIN32
  108. InitializeSRWLock(&m_handle);
  109. #else
  110. pthread_mutex_init(&m_handle, NULL);
  111. #endif
  112. }
  113. ~mutex()
  114. {
  115. #ifdef _WIN32
  116. #else
  117. pthread_mutex_destroy(&m_handle);
  118. #endif
  119. }
  120. void lock()
  121. {
  122. #ifdef _WIN32
  123. AcquireSRWLockExclusive(&m_handle);
  124. #else
  125. pthread_mutex_lock(&m_handle);
  126. #endif
  127. }
  128. void unlock()
  129. {
  130. #ifdef _WIN32
  131. ReleaseSRWLockExclusive(&m_handle);
  132. #else
  133. pthread_mutex_unlock(&m_handle);
  134. #endif
  135. }
  136. bool try_lock()
  137. {
  138. #ifdef _WIN32
  139. // XXX TryAcquireSRWLockExclusive requires Windows 7!
  140. // return (0 != TryAcquireSRWLockExclusive(&m_handle));
  141. return false;
  142. #else
  143. return !pthread_mutex_trylock(&m_handle);
  144. #endif
  145. }
  146. native_handle_type native_handle()
  147. {
  148. return &m_handle;
  149. }
  150. private:
  151. native_type m_handle;
  152. };
  153. #else
  154. typedef recursive_mutex mutex; // just use CriticalSections
  155. #endif
  156. enum defer_lock_t { defer_lock };
  157. enum try_to_lock_t { try_to_lock };
  158. enum adopt_lock_t { adopt_lock };
  159. template <class Mutex>
  160. class lock_guard
  161. {
  162. public:
  163. typedef Mutex mutex_type;
  164. explicit lock_guard(mutex_type& m)
  165. : pm(m)
  166. {
  167. m.lock();
  168. }
  169. lock_guard(mutex_type& m, adopt_lock_t)
  170. : pm(m)
  171. {
  172. }
  173. ~lock_guard()
  174. {
  175. pm.unlock();
  176. }
  177. lock_guard(lock_guard const&) /*= delete*/;
  178. lock_guard& operator=(lock_guard const&) /*= delete*/;
  179. private:
  180. mutex_type& pm;
  181. };
  182. template <class Mutex>
  183. class unique_lock
  184. {
  185. public:
  186. typedef Mutex mutex_type;
  187. unique_lock()
  188. : pm(NULL), owns(false)
  189. {}
  190. /*explicit*/ unique_lock(mutex_type& m)
  191. : pm(&m), owns(true)
  192. {
  193. m.lock();
  194. }
  195. unique_lock(mutex_type& m, defer_lock_t)
  196. : pm(&m), owns(false)
  197. {}
  198. unique_lock(mutex_type& m, try_to_lock_t)
  199. : pm(&m), owns(m.try_lock())
  200. {}
  201. unique_lock(mutex_type& m, adopt_lock_t)
  202. : pm(&m), owns(true)
  203. {}
  204. //template <class Clock, class Duration>
  205. //unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
  206. //template <class Rep, class Period>
  207. //unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
  208. ~unique_lock()
  209. {
  210. if (owns_lock())
  211. mutex()->unlock();
  212. }
  213. #ifdef USE_RVALUE_REFERENCES
  214. unique_lock& operator=(const unique_lock&) /*= delete*/;
  215. unique_lock& operator=(unique_lock&& other)
  216. {
  217. #else
  218. unique_lock& operator=(const unique_lock& u)
  219. {
  220. // ugly const_cast to get around lack of rvalue references
  221. unique_lock& other = const_cast<unique_lock&>(u);
  222. #endif
  223. swap(other);
  224. return *this;
  225. }
  226. #ifdef USE_RVALUE_REFERENCES
  227. unique_lock(const unique_lock&) /*= delete*/;
  228. unique_lock(unique_lock&& other)
  229. : pm(NULL), owns(false)
  230. {
  231. #else
  232. unique_lock(const unique_lock& u)
  233. : pm(NULL), owns(false)
  234. {
  235. // ugly const_cast to get around lack of rvalue references
  236. unique_lock& other = const_cast<unique_lock&>(u);
  237. #endif
  238. swap(other);
  239. }
  240. void lock()
  241. {
  242. mutex()->lock();
  243. owns = true;
  244. }
  245. bool try_lock()
  246. {
  247. owns = mutex()->try_lock();
  248. return owns;
  249. }
  250. //template <class Rep, class Period>
  251. //bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
  252. //template <class Clock, class Duration>
  253. //bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
  254. void unlock()
  255. {
  256. mutex()->unlock();
  257. owns = false;
  258. }
  259. void swap(unique_lock& u)
  260. {
  261. std::swap(pm, u.pm);
  262. std::swap(owns, u.owns);
  263. }
  264. mutex_type* release()
  265. {
  266. auto const ret = mutex();
  267. pm = NULL;
  268. owns = false;
  269. return ret;
  270. }
  271. bool owns_lock() const
  272. {
  273. return owns;
  274. }
  275. //explicit operator bool () const
  276. //{
  277. // return owns_lock();
  278. //}
  279. mutex_type* mutex() const
  280. {
  281. return pm;
  282. }
  283. private:
  284. mutex_type* pm;
  285. bool owns;
  286. };
  287. template <class Mutex>
  288. void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y)
  289. {
  290. x.swap(y);
  291. }
  292. }
  293. #endif