You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

243 lines
5.9KB

  1. // std::unique_lock implementation -*- C++ -*-
  2. // Copyright (C) 2008-2020 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 <chrono>
  31. #include <bits/move.h> // for std::swap
  32. namespace std _GLIBCXX_VISIBILITY(default)
  33. {
  34. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  35. /** @brief A movable scoped lock type.
  36. *
  37. * A unique_lock controls mutex ownership within a scope. Ownership of the
  38. * mutex can be delayed until after construction and can be transferred
  39. * to another unique_lock by move construction or move assignment. If a
  40. * mutex lock is owned when the destructor runs ownership will be released.
  41. *
  42. * @ingroup mutexes
  43. */
  44. template<typename _Mutex>
  45. class unique_lock
  46. {
  47. public:
  48. typedef _Mutex mutex_type;
  49. unique_lock() noexcept
  50. : _M_device(0), _M_owns(false)
  51. { }
  52. explicit unique_lock(mutex_type& __m)
  53. : _M_device(std::__addressof(__m)), _M_owns(false)
  54. {
  55. lock();
  56. _M_owns = true;
  57. }
  58. unique_lock(mutex_type& __m, defer_lock_t) noexcept
  59. : _M_device(std::__addressof(__m)), _M_owns(false)
  60. { }
  61. unique_lock(mutex_type& __m, try_to_lock_t)
  62. : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
  63. { }
  64. unique_lock(mutex_type& __m, adopt_lock_t) noexcept
  65. : _M_device(std::__addressof(__m)), _M_owns(true)
  66. {
  67. // XXX calling thread owns mutex
  68. }
  69. template<typename _Clock, typename _Duration>
  70. unique_lock(mutex_type& __m,
  71. const chrono::time_point<_Clock, _Duration>& __atime)
  72. : _M_device(std::__addressof(__m)),
  73. _M_owns(_M_device->try_lock_until(__atime))
  74. { }
  75. template<typename _Rep, typename _Period>
  76. unique_lock(mutex_type& __m,
  77. const chrono::duration<_Rep, _Period>& __rtime)
  78. : _M_device(std::__addressof(__m)),
  79. _M_owns(_M_device->try_lock_for(__rtime))
  80. { }
  81. ~unique_lock()
  82. {
  83. if (_M_owns)
  84. unlock();
  85. }
  86. unique_lock(const unique_lock&) = delete;
  87. unique_lock& operator=(const unique_lock&) = delete;
  88. unique_lock(unique_lock&& __u) noexcept
  89. : _M_device(__u._M_device), _M_owns(__u._M_owns)
  90. {
  91. __u._M_device = 0;
  92. __u._M_owns = false;
  93. }
  94. unique_lock& operator=(unique_lock&& __u) noexcept
  95. {
  96. if(_M_owns)
  97. unlock();
  98. unique_lock(std::move(__u)).swap(*this);
  99. __u._M_device = 0;
  100. __u._M_owns = false;
  101. return *this;
  102. }
  103. void
  104. lock()
  105. {
  106. if (!_M_device)
  107. __throw_system_error(int(errc::operation_not_permitted));
  108. else if (_M_owns)
  109. __throw_system_error(int(errc::resource_deadlock_would_occur));
  110. else
  111. {
  112. _M_device->lock();
  113. _M_owns = true;
  114. }
  115. }
  116. bool
  117. try_lock()
  118. {
  119. if (!_M_device)
  120. __throw_system_error(int(errc::operation_not_permitted));
  121. else if (_M_owns)
  122. __throw_system_error(int(errc::resource_deadlock_would_occur));
  123. else
  124. {
  125. _M_owns = _M_device->try_lock();
  126. return _M_owns;
  127. }
  128. }
  129. template<typename _Clock, typename _Duration>
  130. bool
  131. try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
  132. {
  133. if (!_M_device)
  134. __throw_system_error(int(errc::operation_not_permitted));
  135. else if (_M_owns)
  136. __throw_system_error(int(errc::resource_deadlock_would_occur));
  137. else
  138. {
  139. _M_owns = _M_device->try_lock_until(__atime);
  140. return _M_owns;
  141. }
  142. }
  143. template<typename _Rep, typename _Period>
  144. bool
  145. try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
  146. {
  147. if (!_M_device)
  148. __throw_system_error(int(errc::operation_not_permitted));
  149. else if (_M_owns)
  150. __throw_system_error(int(errc::resource_deadlock_would_occur));
  151. else
  152. {
  153. _M_owns = _M_device->try_lock_for(__rtime);
  154. return _M_owns;
  155. }
  156. }
  157. void
  158. unlock()
  159. {
  160. if (!_M_owns)
  161. __throw_system_error(int(errc::operation_not_permitted));
  162. else if (_M_device)
  163. {
  164. _M_device->unlock();
  165. _M_owns = false;
  166. }
  167. }
  168. void
  169. swap(unique_lock& __u) noexcept
  170. {
  171. std::swap(_M_device, __u._M_device);
  172. std::swap(_M_owns, __u._M_owns);
  173. }
  174. mutex_type*
  175. release() noexcept
  176. {
  177. mutex_type* __ret = _M_device;
  178. _M_device = 0;
  179. _M_owns = false;
  180. return __ret;
  181. }
  182. bool
  183. owns_lock() const noexcept
  184. { return _M_owns; }
  185. explicit operator bool() const noexcept
  186. { return owns_lock(); }
  187. mutex_type*
  188. mutex() const noexcept
  189. { return _M_device; }
  190. private:
  191. mutex_type* _M_device;
  192. bool _M_owns;
  193. };
  194. /// Swap overload for unique_lock objects.
  195. /// @relates unique_lock
  196. template<typename _Mutex>
  197. inline void
  198. swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
  199. { __x.swap(__y); }
  200. _GLIBCXX_END_NAMESPACE_VERSION
  201. } // namespace
  202. #endif // C++11
  203. #endif // _GLIBCXX_UNIQUE_LOCK_H