__mutex_base 16 KB

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