unique_lock.h 6.0 KB

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