__mutex_base 16 KB

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