__mutex_base 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef _LIBCPP___MUTEX_BASE
  10. #define _LIBCPP___MUTEX_BASE
  11. #include <__config>
  12. #include <__threading_support>
  13. #include <chrono>
  14. #include <ratio>
  15. #include <system_error>
  16. #include <time.h>
  17. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  18. # pragma GCC system_header
  19. #endif
  20. _LIBCPP_PUSH_MACROS
  21. #include <__undef_macros>
  22. _LIBCPP_BEGIN_NAMESPACE_STD
  23. #ifndef _LIBCPP_HAS_NO_THREADS
  24. class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
  25. {
  26. __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
  27. public:
  28. _LIBCPP_INLINE_VISIBILITY
  29. _LIBCPP_CONSTEXPR mutex() = default;
  30. mutex(const mutex&) = delete;
  31. mutex& operator=(const mutex&) = delete;
  32. #if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION)
  33. ~mutex() = default;
  34. #else
  35. ~mutex() _NOEXCEPT;
  36. #endif
  37. void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
  38. bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
  39. void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
  40. typedef __libcpp_mutex_t* native_handle_type;
  41. _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
  42. };
  43. static_assert(is_nothrow_default_constructible<mutex>::value,
  44. "the default constructor for std::mutex must be nothrow");
  45. struct _LIBCPP_TYPE_VIS defer_lock_t { explicit defer_lock_t() = default; };
  46. struct _LIBCPP_TYPE_VIS try_to_lock_t { explicit try_to_lock_t() = default; };
  47. struct _LIBCPP_TYPE_VIS adopt_lock_t { explicit adopt_lock_t() = default; };
  48. #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
  49. extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock;
  50. extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock;
  51. extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock;
  52. #else
  53. /* inline */ constexpr defer_lock_t defer_lock = defer_lock_t();
  54. /* inline */ constexpr try_to_lock_t try_to_lock = try_to_lock_t();
  55. /* inline */ constexpr adopt_lock_t adopt_lock = adopt_lock_t();
  56. #endif
  57. template <class _Mutex>
  58. class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
  59. lock_guard
  60. {
  61. public:
  62. typedef _Mutex mutex_type;
  63. private:
  64. mutex_type& __m_;
  65. public:
  66. _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY
  67. explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
  68. : __m_(__m) {__m_.lock();}
  69. _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY
  70. lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
  71. : __m_(__m) {}
  72. _LIBCPP_INLINE_VISIBILITY
  73. ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
  74. private:
  75. lock_guard(lock_guard const&) = delete;
  76. lock_guard& operator=(lock_guard const&) = delete;
  77. };
  78. template <class _Mutex>
  79. class _LIBCPP_TEMPLATE_VIS unique_lock
  80. {
  81. public:
  82. typedef _Mutex mutex_type;
  83. private:
  84. mutex_type* __m_;
  85. bool __owns_;
  86. public:
  87. _LIBCPP_INLINE_VISIBILITY
  88. unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
  89. _LIBCPP_INLINE_VISIBILITY
  90. explicit unique_lock(mutex_type& __m)
  91. : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();}
  92. _LIBCPP_INLINE_VISIBILITY
  93. unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
  94. : __m_(_VSTD::addressof(__m)), __owns_(false) {}
  95. _LIBCPP_INLINE_VISIBILITY
  96. unique_lock(mutex_type& __m, try_to_lock_t)
  97. : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {}
  98. _LIBCPP_INLINE_VISIBILITY
  99. unique_lock(mutex_type& __m, adopt_lock_t)
  100. : __m_(_VSTD::addressof(__m)), __owns_(true) {}
  101. template <class _Clock, class _Duration>
  102. _LIBCPP_INLINE_VISIBILITY
  103. unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
  104. : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {}
  105. template <class _Rep, class _Period>
  106. _LIBCPP_INLINE_VISIBILITY
  107. unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
  108. : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {}
  109. _LIBCPP_INLINE_VISIBILITY
  110. ~unique_lock()
  111. {
  112. if (__owns_)
  113. __m_->unlock();
  114. }
  115. unique_lock(unique_lock const&) = delete;
  116. unique_lock& operator=(unique_lock const&) = delete;
  117. _LIBCPP_INLINE_VISIBILITY
  118. unique_lock(unique_lock&& __u) _NOEXCEPT
  119. : __m_(__u.__m_), __owns_(__u.__owns_)
  120. {__u.__m_ = nullptr; __u.__owns_ = false;}
  121. _LIBCPP_INLINE_VISIBILITY
  122. unique_lock& operator=(unique_lock&& __u) _NOEXCEPT
  123. {
  124. if (__owns_)
  125. __m_->unlock();
  126. __m_ = __u.__m_;
  127. __owns_ = __u.__owns_;
  128. __u.__m_ = nullptr;
  129. __u.__owns_ = false;
  130. return *this;
  131. }
  132. void lock();
  133. bool try_lock();
  134. template <class _Rep, class _Period>
  135. bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
  136. template <class _Clock, class _Duration>
  137. bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
  138. void unlock();
  139. _LIBCPP_INLINE_VISIBILITY
  140. void swap(unique_lock& __u) _NOEXCEPT
  141. {
  142. _VSTD::swap(__m_, __u.__m_);
  143. _VSTD::swap(__owns_, __u.__owns_);
  144. }
  145. _LIBCPP_INLINE_VISIBILITY
  146. mutex_type* release() _NOEXCEPT
  147. {
  148. mutex_type* __m = __m_;
  149. __m_ = nullptr;
  150. __owns_ = false;
  151. return __m;
  152. }
  153. _LIBCPP_INLINE_VISIBILITY
  154. bool owns_lock() const _NOEXCEPT {return __owns_;}
  155. _LIBCPP_INLINE_VISIBILITY
  156. explicit operator bool() const _NOEXCEPT {return __owns_;}
  157. _LIBCPP_INLINE_VISIBILITY
  158. mutex_type* mutex() const _NOEXCEPT {return __m_;}
  159. };
  160. template <class _Mutex>
  161. void
  162. unique_lock<_Mutex>::lock()
  163. {
  164. if (__m_ == nullptr)
  165. __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
  166. if (__owns_)
  167. __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
  168. __m_->lock();
  169. __owns_ = true;
  170. }
  171. template <class _Mutex>
  172. bool
  173. unique_lock<_Mutex>::try_lock()
  174. {
  175. if (__m_ == nullptr)
  176. __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
  177. if (__owns_)
  178. __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
  179. __owns_ = __m_->try_lock();
  180. return __owns_;
  181. }
  182. template <class _Mutex>
  183. template <class _Rep, class _Period>
  184. bool
  185. unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
  186. {
  187. if (__m_ == nullptr)
  188. __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
  189. if (__owns_)
  190. __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
  191. __owns_ = __m_->try_lock_for(__d);
  192. return __owns_;
  193. }
  194. template <class _Mutex>
  195. template <class _Clock, class _Duration>
  196. bool
  197. unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
  198. {
  199. if (__m_ == nullptr)
  200. __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
  201. if (__owns_)
  202. __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
  203. __owns_ = __m_->try_lock_until(__t);
  204. return __owns_;
  205. }
  206. template <class _Mutex>
  207. void
  208. unique_lock<_Mutex>::unlock()
  209. {
  210. if (!__owns_)
  211. __throw_system_error(EPERM, "unique_lock::unlock: not locked");
  212. __m_->unlock();
  213. __owns_ = false;
  214. }
  215. template <class _Mutex>
  216. inline _LIBCPP_INLINE_VISIBILITY
  217. void
  218. swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT
  219. {__x.swap(__y);}
  220. //enum class cv_status
  221. _LIBCPP_DECLARE_STRONG_ENUM(cv_status)
  222. {
  223. no_timeout,
  224. timeout
  225. };
  226. _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
  227. class _LIBCPP_TYPE_VIS condition_variable
  228. {
  229. __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
  230. public:
  231. _LIBCPP_INLINE_VISIBILITY
  232. _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
  233. #ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
  234. ~condition_variable() = default;
  235. #else
  236. ~condition_variable();
  237. #endif
  238. condition_variable(const condition_variable&) = delete;
  239. condition_variable& operator=(const condition_variable&) = delete;
  240. void notify_one() _NOEXCEPT;
  241. void notify_all() _NOEXCEPT;
  242. void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
  243. template <class _Predicate>
  244. _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
  245. void wait(unique_lock<mutex>& __lk, _Predicate __pred);
  246. template <class _Clock, class _Duration>
  247. _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
  248. cv_status
  249. wait_until(unique_lock<mutex>& __lk,
  250. const chrono::time_point<_Clock, _Duration>& __t);
  251. template <class _Clock, class _Duration, class _Predicate>
  252. _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
  253. bool
  254. wait_until(unique_lock<mutex>& __lk,
  255. const chrono::time_point<_Clock, _Duration>& __t,
  256. _Predicate __pred);
  257. template <class _Rep, class _Period>
  258. _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
  259. cv_status
  260. wait_for(unique_lock<mutex>& __lk,
  261. const chrono::duration<_Rep, _Period>& __d);
  262. template <class _Rep, class _Period, class _Predicate>
  263. bool
  264. _LIBCPP_INLINE_VISIBILITY
  265. wait_for(unique_lock<mutex>& __lk,
  266. const chrono::duration<_Rep, _Period>& __d,
  267. _Predicate __pred);
  268. typedef __libcpp_condvar_t* native_handle_type;
  269. _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;}
  270. private:
  271. void __do_timed_wait(unique_lock<mutex>& __lk,
  272. chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
  273. #if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
  274. void __do_timed_wait(unique_lock<mutex>& __lk,
  275. chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT;
  276. #endif
  277. template <class _Clock>
  278. void __do_timed_wait(unique_lock<mutex>& __lk,
  279. chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT;
  280. };
  281. #endif // !_LIBCPP_HAS_NO_THREADS
  282. template <class _Rep, class _Period>
  283. inline _LIBCPP_INLINE_VISIBILITY
  284. typename enable_if
  285. <
  286. is_floating_point<_Rep>::value,
  287. chrono::nanoseconds
  288. >::type
  289. __safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d)
  290. {
  291. using namespace chrono;
  292. using __ratio = ratio_divide<_Period, nano>;
  293. using __ns_rep = nanoseconds::rep;
  294. _Rep __result_float = __d.count() * __ratio::num / __ratio::den;
  295. _Rep __result_max = numeric_limits<__ns_rep>::max();
  296. if (__result_float >= __result_max) {
  297. return nanoseconds::max();
  298. }
  299. _Rep __result_min = numeric_limits<__ns_rep>::min();
  300. if (__result_float <= __result_min) {
  301. return nanoseconds::min();
  302. }
  303. return nanoseconds(static_cast<__ns_rep>(__result_float));
  304. }
  305. template <class _Rep, class _Period>
  306. inline _LIBCPP_INLINE_VISIBILITY
  307. typename enable_if
  308. <
  309. !is_floating_point<_Rep>::value,
  310. chrono::nanoseconds
  311. >::type
  312. __safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d)
  313. {
  314. using namespace chrono;
  315. if (__d.count() == 0) {
  316. return nanoseconds(0);
  317. }
  318. using __ratio = ratio_divide<_Period, nano>;
  319. using __ns_rep = nanoseconds::rep;
  320. __ns_rep __result_max = numeric_limits<__ns_rep>::max();
  321. if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) {
  322. return nanoseconds::max();
  323. }
  324. __ns_rep __result_min = numeric_limits<__ns_rep>::min();
  325. if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) {
  326. return nanoseconds::min();
  327. }
  328. __ns_rep __result = __d.count() * __ratio::num / __ratio::den;
  329. if (__result == 0) {
  330. return nanoseconds(1);
  331. }
  332. return nanoseconds(__result);
  333. }
  334. #ifndef _LIBCPP_HAS_NO_THREADS
  335. template <class _Predicate>
  336. void
  337. condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred)
  338. {
  339. while (!__pred())
  340. wait(__lk);
  341. }
  342. template <class _Clock, class _Duration>
  343. cv_status
  344. condition_variable::wait_until(unique_lock<mutex>& __lk,
  345. const chrono::time_point<_Clock, _Duration>& __t)
  346. {
  347. using namespace chrono;
  348. using __clock_tp_ns = time_point<_Clock, nanoseconds>;
  349. typename _Clock::time_point __now = _Clock::now();
  350. if (__t <= __now)
  351. return cv_status::timeout;
  352. __clock_tp_ns __t_ns = __clock_tp_ns(_VSTD::__safe_nanosecond_cast(__t.time_since_epoch()));
  353. __do_timed_wait(__lk, __t_ns);
  354. return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
  355. }
  356. template <class _Clock, class _Duration, class _Predicate>
  357. bool
  358. condition_variable::wait_until(unique_lock<mutex>& __lk,
  359. const chrono::time_point<_Clock, _Duration>& __t,
  360. _Predicate __pred)
  361. {
  362. while (!__pred())
  363. {
  364. if (wait_until(__lk, __t) == cv_status::timeout)
  365. return __pred();
  366. }
  367. return true;
  368. }
  369. template <class _Rep, class _Period>
  370. cv_status
  371. condition_variable::wait_for(unique_lock<mutex>& __lk,
  372. const chrono::duration<_Rep, _Period>& __d)
  373. {
  374. using namespace chrono;
  375. if (__d <= __d.zero())
  376. return cv_status::timeout;
  377. using __ns_rep = nanoseconds::rep;
  378. steady_clock::time_point __c_now = steady_clock::now();
  379. #if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
  380. using __clock_tp_ns = time_point<steady_clock, nanoseconds>;
  381. __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(__c_now.time_since_epoch()).count();
  382. #else
  383. using __clock_tp_ns = time_point<system_clock, nanoseconds>;
  384. __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count();
  385. #endif
  386. __ns_rep __d_ns_count = _VSTD::__safe_nanosecond_cast(__d).count();
  387. if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) {
  388. __do_timed_wait(__lk, __clock_tp_ns::max());
  389. } else {
  390. __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count)));
  391. }
  392. return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
  393. cv_status::timeout;
  394. }
  395. template <class _Rep, class _Period, class _Predicate>
  396. inline
  397. bool
  398. condition_variable::wait_for(unique_lock<mutex>& __lk,
  399. const chrono::duration<_Rep, _Period>& __d,
  400. _Predicate __pred)
  401. {
  402. return wait_until(__lk, chrono::steady_clock::now() + __d,
  403. _VSTD::move(__pred));
  404. }
  405. #if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
  406. inline
  407. void
  408. condition_variable::__do_timed_wait(unique_lock<mutex>& __lk,
  409. chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT
  410. {
  411. using namespace chrono;
  412. if (!__lk.owns_lock())
  413. __throw_system_error(EPERM,
  414. "condition_variable::timed wait: mutex not locked");
  415. nanoseconds __d = __tp.time_since_epoch();
  416. timespec __ts;
  417. seconds __s = duration_cast<seconds>(__d);
  418. using __ts_sec = decltype(__ts.tv_sec);
  419. const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
  420. if (__s.count() < __ts_sec_max)
  421. {
  422. __ts.tv_sec = static_cast<__ts_sec>(__s.count());
  423. __ts.tv_nsec = (__d - __s).count();
  424. }
  425. else
  426. {
  427. __ts.tv_sec = __ts_sec_max;
  428. __ts.tv_nsec = giga::num - 1;
  429. }
  430. int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts);
  431. if (__ec != 0 && __ec != ETIMEDOUT)
  432. __throw_system_error(__ec, "condition_variable timed_wait failed");
  433. }
  434. #endif // _LIBCPP_HAS_COND_CLOCKWAIT
  435. template <class _Clock>
  436. inline
  437. void
  438. condition_variable::__do_timed_wait(unique_lock<mutex>& __lk,
  439. chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT
  440. {
  441. wait_for(__lk, __tp - _Clock::now());
  442. }
  443. #endif // !_LIBCPP_HAS_NO_THREADS
  444. _LIBCPP_END_NAMESPACE_STD
  445. _LIBCPP_POP_MACROS
  446. #endif // _LIBCPP___MUTEX_BASE