__mutex_base 16 KB

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