unique_lock.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef _LIBCPP___MUTEX_UNIQUE_LOCK_H
  9. #define _LIBCPP___MUTEX_UNIQUE_LOCK_H
  10. #include <__chrono/duration.h>
  11. #include <__chrono/time_point.h>
  12. #include <__config>
  13. #include <__memory/addressof.h>
  14. #include <__mutex/tag_types.h>
  15. #include <__system_error/system_error.h>
  16. #include <__utility/swap.h>
  17. #include <cerrno>
  18. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  19. # pragma GCC system_header
  20. #endif
  21. #ifndef _LIBCPP_HAS_NO_THREADS
  22. _LIBCPP_BEGIN_NAMESPACE_STD
  23. template <class _Mutex>
  24. class _LIBCPP_TEMPLATE_VIS unique_lock {
  25. public:
  26. typedef _Mutex mutex_type;
  27. private:
  28. mutex_type* __m_;
  29. bool __owns_;
  30. public:
  31. _LIBCPP_HIDE_FROM_ABI unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {}
  32. _LIBCPP_HIDE_FROM_ABI explicit unique_lock(mutex_type& __m) : __m_(std::addressof(__m)), __owns_(true) {
  33. __m_->lock();
  34. }
  35. _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
  36. : __m_(std::addressof(__m)),
  37. __owns_(false) {}
  38. _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, try_to_lock_t)
  39. : __m_(std::addressof(__m)), __owns_(__m.try_lock()) {}
  40. _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, adopt_lock_t) : __m_(std::addressof(__m)), __owns_(true) {}
  41. template <class _Clock, class _Duration>
  42. _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t)
  43. : __m_(std::addressof(__m)), __owns_(__m.try_lock_until(__t)) {}
  44. template <class _Rep, class _Period>
  45. _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d)
  46. : __m_(std::addressof(__m)), __owns_(__m.try_lock_for(__d)) {}
  47. _LIBCPP_HIDE_FROM_ABI ~unique_lock() {
  48. if (__owns_)
  49. __m_->unlock();
  50. }
  51. unique_lock(unique_lock const&) = delete;
  52. unique_lock& operator=(unique_lock const&) = delete;
  53. _LIBCPP_HIDE_FROM_ABI unique_lock(unique_lock&& __u) _NOEXCEPT : __m_(__u.__m_), __owns_(__u.__owns_) {
  54. __u.__m_ = nullptr;
  55. __u.__owns_ = false;
  56. }
  57. _LIBCPP_HIDE_FROM_ABI unique_lock& operator=(unique_lock&& __u) _NOEXCEPT {
  58. if (__owns_)
  59. __m_->unlock();
  60. __m_ = __u.__m_;
  61. __owns_ = __u.__owns_;
  62. __u.__m_ = nullptr;
  63. __u.__owns_ = false;
  64. return *this;
  65. }
  66. void lock();
  67. bool try_lock();
  68. template <class _Rep, class _Period>
  69. bool try_lock_for(const chrono::duration<_Rep, _Period>& __d);
  70. template <class _Clock, class _Duration>
  71. bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
  72. void unlock();
  73. _LIBCPP_HIDE_FROM_ABI void swap(unique_lock& __u) _NOEXCEPT {
  74. std::swap(__m_, __u.__m_);
  75. std::swap(__owns_, __u.__owns_);
  76. }
  77. _LIBCPP_HIDE_FROM_ABI mutex_type* release() _NOEXCEPT {
  78. mutex_type* __m = __m_;
  79. __m_ = nullptr;
  80. __owns_ = false;
  81. return __m;
  82. }
  83. _LIBCPP_HIDE_FROM_ABI bool owns_lock() const _NOEXCEPT { return __owns_; }
  84. _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __owns_; }
  85. _LIBCPP_HIDE_FROM_ABI mutex_type* mutex() const _NOEXCEPT { return __m_; }
  86. };
  87. _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(unique_lock);
  88. template <class _Mutex>
  89. void unique_lock<_Mutex>::lock() {
  90. if (__m_ == nullptr)
  91. __throw_system_error(EPERM, "unique_lock::lock: references null mutex");
  92. if (__owns_)
  93. __throw_system_error(EDEADLK, "unique_lock::lock: already locked");
  94. __m_->lock();
  95. __owns_ = true;
  96. }
  97. template <class _Mutex>
  98. bool unique_lock<_Mutex>::try_lock() {
  99. if (__m_ == nullptr)
  100. __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex");
  101. if (__owns_)
  102. __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked");
  103. __owns_ = __m_->try_lock();
  104. return __owns_;
  105. }
  106. template <class _Mutex>
  107. template <class _Rep, class _Period>
  108. bool unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) {
  109. if (__m_ == nullptr)
  110. __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex");
  111. if (__owns_)
  112. __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked");
  113. __owns_ = __m_->try_lock_for(__d);
  114. return __owns_;
  115. }
  116. template <class _Mutex>
  117. template <class _Clock, class _Duration>
  118. bool unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) {
  119. if (__m_ == nullptr)
  120. __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex");
  121. if (__owns_)
  122. __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked");
  123. __owns_ = __m_->try_lock_until(__t);
  124. return __owns_;
  125. }
  126. template <class _Mutex>
  127. void unique_lock<_Mutex>::unlock() {
  128. if (!__owns_)
  129. __throw_system_error(EPERM, "unique_lock::unlock: not locked");
  130. __m_->unlock();
  131. __owns_ = false;
  132. }
  133. template <class _Mutex>
  134. inline _LIBCPP_HIDE_FROM_ABI void swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT {
  135. __x.swap(__y);
  136. }
  137. _LIBCPP_END_NAMESPACE_STD
  138. #endif // _LIBCPP_HAS_NO_THREADS
  139. #endif // _LIBCPP___MUTEX_UNIQUE_LOCK_H