unique_lock.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // std::unique_lock implementation -*- C++ -*-
  2. // Copyright (C) 2008-2022 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file bits/unique_lock.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{mutex}
  23. */
  24. #ifndef _GLIBCXX_UNIQUE_LOCK_H
  25. #define _GLIBCXX_UNIQUE_LOCK_H 1
  26. #pragma GCC system_header
  27. #if __cplusplus < 201103L
  28. # include <bits/c++0x_warning.h>
  29. #else
  30. #include <bits/chrono.h>
  31. #include <bits/move.h> // for std::swap
  32. #include <bits/std_mutex.h> // for std::defer_lock_t
  33. namespace std _GLIBCXX_VISIBILITY(default)
  34. {
  35. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  36. /** @brief A movable scoped lock type.
  37. *
  38. * A unique_lock controls mutex ownership within a scope. Ownership of the
  39. * mutex can be delayed until after construction and can be transferred
  40. * to another unique_lock by move construction or move assignment. If a
  41. * mutex lock is owned when the destructor runs ownership will be released.
  42. *
  43. * @ingroup mutexes
  44. */
  45. template<typename _Mutex>
  46. class unique_lock
  47. {
  48. public:
  49. typedef _Mutex mutex_type;
  50. unique_lock() noexcept
  51. : _M_device(0), _M_owns(false)
  52. { }
  53. explicit unique_lock(mutex_type& __m)
  54. : _M_device(std::__addressof(__m)), _M_owns(false)
  55. {
  56. lock();
  57. _M_owns = true;
  58. }
  59. unique_lock(mutex_type& __m, defer_lock_t) noexcept
  60. : _M_device(std::__addressof(__m)), _M_owns(false)
  61. { }
  62. unique_lock(mutex_type& __m, try_to_lock_t)
  63. : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
  64. { }
  65. unique_lock(mutex_type& __m, adopt_lock_t) noexcept
  66. : _M_device(std::__addressof(__m)), _M_owns(true)
  67. {
  68. // XXX calling thread owns mutex
  69. }
  70. template<typename _Clock, typename _Duration>
  71. unique_lock(mutex_type& __m,
  72. const chrono::time_point<_Clock, _Duration>& __atime)
  73. : _M_device(std::__addressof(__m)),
  74. _M_owns(_M_device->try_lock_until(__atime))
  75. { }
  76. template<typename _Rep, typename _Period>
  77. unique_lock(mutex_type& __m,
  78. const chrono::duration<_Rep, _Period>& __rtime)
  79. : _M_device(std::__addressof(__m)),
  80. _M_owns(_M_device->try_lock_for(__rtime))
  81. { }
  82. ~unique_lock()
  83. {
  84. if (_M_owns)
  85. unlock();
  86. }
  87. unique_lock(const unique_lock&) = delete;
  88. unique_lock& operator=(const unique_lock&) = delete;
  89. unique_lock(unique_lock&& __u) noexcept
  90. : _M_device(__u._M_device), _M_owns(__u._M_owns)
  91. {
  92. __u._M_device = 0;
  93. __u._M_owns = false;
  94. }
  95. unique_lock& operator=(unique_lock&& __u) noexcept
  96. {
  97. if(_M_owns)
  98. unlock();
  99. unique_lock(std::move(__u)).swap(*this);
  100. __u._M_device = 0;
  101. __u._M_owns = false;
  102. return *this;
  103. }
  104. void
  105. lock()
  106. {
  107. if (!_M_device)
  108. __throw_system_error(int(errc::operation_not_permitted));
  109. else if (_M_owns)
  110. __throw_system_error(int(errc::resource_deadlock_would_occur));
  111. else
  112. {
  113. _M_device->lock();
  114. _M_owns = true;
  115. }
  116. }
  117. bool
  118. try_lock()
  119. {
  120. if (!_M_device)
  121. __throw_system_error(int(errc::operation_not_permitted));
  122. else if (_M_owns)
  123. __throw_system_error(int(errc::resource_deadlock_would_occur));
  124. else
  125. {
  126. _M_owns = _M_device->try_lock();
  127. return _M_owns;
  128. }
  129. }
  130. template<typename _Clock, typename _Duration>
  131. bool
  132. try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
  133. {
  134. if (!_M_device)
  135. __throw_system_error(int(errc::operation_not_permitted));
  136. else if (_M_owns)
  137. __throw_system_error(int(errc::resource_deadlock_would_occur));
  138. else
  139. {
  140. _M_owns = _M_device->try_lock_until(__atime);
  141. return _M_owns;
  142. }
  143. }
  144. template<typename _Rep, typename _Period>
  145. bool
  146. try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
  147. {
  148. if (!_M_device)
  149. __throw_system_error(int(errc::operation_not_permitted));
  150. else if (_M_owns)
  151. __throw_system_error(int(errc::resource_deadlock_would_occur));
  152. else
  153. {
  154. _M_owns = _M_device->try_lock_for(__rtime);
  155. return _M_owns;
  156. }
  157. }
  158. void
  159. unlock()
  160. {
  161. if (!_M_owns)
  162. __throw_system_error(int(errc::operation_not_permitted));
  163. else if (_M_device)
  164. {
  165. _M_device->unlock();
  166. _M_owns = false;
  167. }
  168. }
  169. void
  170. swap(unique_lock& __u) noexcept
  171. {
  172. std::swap(_M_device, __u._M_device);
  173. std::swap(_M_owns, __u._M_owns);
  174. }
  175. mutex_type*
  176. release() noexcept
  177. {
  178. mutex_type* __ret = _M_device;
  179. _M_device = 0;
  180. _M_owns = false;
  181. return __ret;
  182. }
  183. bool
  184. owns_lock() const noexcept
  185. { return _M_owns; }
  186. explicit operator bool() const noexcept
  187. { return owns_lock(); }
  188. mutex_type*
  189. mutex() const noexcept
  190. { return _M_device; }
  191. private:
  192. mutex_type* _M_device;
  193. bool _M_owns;
  194. };
  195. /// Swap overload for unique_lock objects.
  196. /// @relates unique_lock
  197. template<typename _Mutex>
  198. inline void
  199. swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
  200. { __x.swap(__y); }
  201. _GLIBCXX_END_NAMESPACE_VERSION
  202. } // namespace
  203. #endif // C++11
  204. #endif // _GLIBCXX_UNIQUE_LOCK_H