mutex 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. // <mutex> -*- C++ -*-
  2. // Copyright (C) 2003-2016 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 include/mutex
  21. * This is a Standard C++ Library header.
  22. */
  23. #ifndef _GLIBCXX_MUTEX
  24. #define _GLIBCXX_MUTEX 1
  25. #pragma GCC system_header
  26. #if __cplusplus < 201103L
  27. # include <bits/c++0x_warning.h>
  28. #else
  29. #include <tuple>
  30. #include <chrono>
  31. #include <exception>
  32. #include <type_traits>
  33. #include <functional>
  34. #include <system_error>
  35. #include <bits/std_mutex.h>
  36. #if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
  37. # include <condition_variable>
  38. # include <thread>
  39. #endif
  40. #ifdef _GLIBCXX_USE_C99_STDINT_TR1
  41. namespace std _GLIBCXX_VISIBILITY(default)
  42. {
  43. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  44. /**
  45. * @ingroup mutexes
  46. * @{
  47. */
  48. #ifdef _GLIBCXX_HAS_GTHREADS
  49. // Common base class for std::recursive_mutex and std::recursive_timed_mutex
  50. class __recursive_mutex_base
  51. {
  52. protected:
  53. typedef __gthread_recursive_mutex_t __native_type;
  54. __recursive_mutex_base(const __recursive_mutex_base&) = delete;
  55. __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
  56. #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
  57. __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
  58. __recursive_mutex_base() = default;
  59. #else
  60. __native_type _M_mutex;
  61. __recursive_mutex_base()
  62. {
  63. // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
  64. __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
  65. }
  66. ~__recursive_mutex_base()
  67. { __gthread_recursive_mutex_destroy(&_M_mutex); }
  68. #endif
  69. };
  70. /// The standard recursive mutex type.
  71. class recursive_mutex : private __recursive_mutex_base
  72. {
  73. public:
  74. typedef __native_type* native_handle_type;
  75. recursive_mutex() = default;
  76. ~recursive_mutex() = default;
  77. recursive_mutex(const recursive_mutex&) = delete;
  78. recursive_mutex& operator=(const recursive_mutex&) = delete;
  79. void
  80. lock()
  81. {
  82. int __e = __gthread_recursive_mutex_lock(&_M_mutex);
  83. // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
  84. if (__e)
  85. __throw_system_error(__e);
  86. }
  87. bool
  88. try_lock() noexcept
  89. {
  90. // XXX EINVAL, EAGAIN, EBUSY
  91. return !__gthread_recursive_mutex_trylock(&_M_mutex);
  92. }
  93. void
  94. unlock()
  95. {
  96. // XXX EINVAL, EAGAIN, EBUSY
  97. __gthread_recursive_mutex_unlock(&_M_mutex);
  98. }
  99. native_handle_type
  100. native_handle()
  101. { return &_M_mutex; }
  102. };
  103. #if _GTHREAD_USE_MUTEX_TIMEDLOCK
  104. template<typename _Derived>
  105. class __timed_mutex_impl
  106. {
  107. protected:
  108. typedef chrono::high_resolution_clock __clock_t;
  109. template<typename _Rep, typename _Period>
  110. bool
  111. _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
  112. {
  113. using chrono::steady_clock;
  114. auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
  115. if (ratio_greater<steady_clock::period, _Period>())
  116. ++__rt;
  117. return _M_try_lock_until(steady_clock::now() + __rt);
  118. }
  119. template<typename _Duration>
  120. bool
  121. _M_try_lock_until(const chrono::time_point<__clock_t,
  122. _Duration>& __atime)
  123. {
  124. auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
  125. auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
  126. __gthread_time_t __ts = {
  127. static_cast<std::time_t>(__s.time_since_epoch().count()),
  128. static_cast<long>(__ns.count())
  129. };
  130. return static_cast<_Derived*>(this)->_M_timedlock(__ts);
  131. }
  132. template<typename _Clock, typename _Duration>
  133. bool
  134. _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
  135. {
  136. auto __rtime = __atime - _Clock::now();
  137. return _M_try_lock_until(__clock_t::now() + __rtime);
  138. }
  139. };
  140. /// The standard timed mutex type.
  141. class timed_mutex
  142. : private __mutex_base, public __timed_mutex_impl<timed_mutex>
  143. {
  144. public:
  145. typedef __native_type* native_handle_type;
  146. timed_mutex() = default;
  147. ~timed_mutex() = default;
  148. timed_mutex(const timed_mutex&) = delete;
  149. timed_mutex& operator=(const timed_mutex&) = delete;
  150. void
  151. lock()
  152. {
  153. int __e = __gthread_mutex_lock(&_M_mutex);
  154. // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
  155. if (__e)
  156. __throw_system_error(__e);
  157. }
  158. bool
  159. try_lock() noexcept
  160. {
  161. // XXX EINVAL, EAGAIN, EBUSY
  162. return !__gthread_mutex_trylock(&_M_mutex);
  163. }
  164. template <class _Rep, class _Period>
  165. bool
  166. try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
  167. { return _M_try_lock_for(__rtime); }
  168. template <class _Clock, class _Duration>
  169. bool
  170. try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
  171. { return _M_try_lock_until(__atime); }
  172. void
  173. unlock()
  174. {
  175. // XXX EINVAL, EAGAIN, EBUSY
  176. __gthread_mutex_unlock(&_M_mutex);
  177. }
  178. native_handle_type
  179. native_handle()
  180. { return &_M_mutex; }
  181. private:
  182. friend class __timed_mutex_impl<timed_mutex>;
  183. bool
  184. _M_timedlock(const __gthread_time_t& __ts)
  185. { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
  186. };
  187. /// recursive_timed_mutex
  188. class recursive_timed_mutex
  189. : private __recursive_mutex_base,
  190. public __timed_mutex_impl<recursive_timed_mutex>
  191. {
  192. public:
  193. typedef __native_type* native_handle_type;
  194. recursive_timed_mutex() = default;
  195. ~recursive_timed_mutex() = default;
  196. recursive_timed_mutex(const recursive_timed_mutex&) = delete;
  197. recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
  198. void
  199. lock()
  200. {
  201. int __e = __gthread_recursive_mutex_lock(&_M_mutex);
  202. // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
  203. if (__e)
  204. __throw_system_error(__e);
  205. }
  206. bool
  207. try_lock() noexcept
  208. {
  209. // XXX EINVAL, EAGAIN, EBUSY
  210. return !__gthread_recursive_mutex_trylock(&_M_mutex);
  211. }
  212. template <class _Rep, class _Period>
  213. bool
  214. try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
  215. { return _M_try_lock_for(__rtime); }
  216. template <class _Clock, class _Duration>
  217. bool
  218. try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
  219. { return _M_try_lock_until(__atime); }
  220. void
  221. unlock()
  222. {
  223. // XXX EINVAL, EAGAIN, EBUSY
  224. __gthread_recursive_mutex_unlock(&_M_mutex);
  225. }
  226. native_handle_type
  227. native_handle()
  228. { return &_M_mutex; }
  229. private:
  230. friend class __timed_mutex_impl<recursive_timed_mutex>;
  231. bool
  232. _M_timedlock(const __gthread_time_t& __ts)
  233. { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
  234. };
  235. #else // !_GTHREAD_USE_MUTEX_TIMEDLOCK
  236. /// timed_mutex
  237. class timed_mutex
  238. {
  239. mutex _M_mut;
  240. condition_variable _M_cv;
  241. bool _M_locked = false;
  242. public:
  243. timed_mutex() = default;
  244. ~timed_mutex() { __glibcxx_assert( !_M_locked ); }
  245. timed_mutex(const timed_mutex&) = delete;
  246. timed_mutex& operator=(const timed_mutex&) = delete;
  247. void
  248. lock()
  249. {
  250. unique_lock<mutex> __lk(_M_mut);
  251. _M_cv.wait(__lk, [&]{ return !_M_locked; });
  252. _M_locked = true;
  253. }
  254. bool
  255. try_lock()
  256. {
  257. lock_guard<mutex> __lk(_M_mut);
  258. if (_M_locked)
  259. return false;
  260. _M_locked = true;
  261. return true;
  262. }
  263. template<typename _Rep, typename _Period>
  264. bool
  265. try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
  266. {
  267. unique_lock<mutex> __lk(_M_mut);
  268. if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
  269. return false;
  270. _M_locked = true;
  271. return true;
  272. }
  273. template<typename _Clock, typename _Duration>
  274. bool
  275. try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
  276. {
  277. unique_lock<mutex> __lk(_M_mut);
  278. if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
  279. return false;
  280. _M_locked = true;
  281. return true;
  282. }
  283. void
  284. unlock()
  285. {
  286. lock_guard<mutex> __lk(_M_mut);
  287. __glibcxx_assert( _M_locked );
  288. _M_locked = false;
  289. _M_cv.notify_one();
  290. }
  291. };
  292. /// recursive_timed_mutex
  293. class recursive_timed_mutex
  294. {
  295. mutex _M_mut;
  296. condition_variable _M_cv;
  297. thread::id _M_owner;
  298. unsigned _M_count = 0;
  299. // Predicate type that tests whether the current thread can lock a mutex.
  300. struct _Can_lock
  301. {
  302. // Returns true if the mutex is unlocked or is locked by _M_caller.
  303. bool
  304. operator()() const noexcept
  305. { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; }
  306. const recursive_timed_mutex* _M_mx;
  307. thread::id _M_caller;
  308. };
  309. public:
  310. recursive_timed_mutex() = default;
  311. ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
  312. recursive_timed_mutex(const recursive_timed_mutex&) = delete;
  313. recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
  314. void
  315. lock()
  316. {
  317. auto __id = this_thread::get_id();
  318. _Can_lock __can_lock{this, __id};
  319. unique_lock<mutex> __lk(_M_mut);
  320. _M_cv.wait(__lk, __can_lock);
  321. if (_M_count == -1u)
  322. __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3
  323. _M_owner = __id;
  324. ++_M_count;
  325. }
  326. bool
  327. try_lock()
  328. {
  329. auto __id = this_thread::get_id();
  330. _Can_lock __can_lock{this, __id};
  331. lock_guard<mutex> __lk(_M_mut);
  332. if (!__can_lock())
  333. return false;
  334. if (_M_count == -1u)
  335. return false;
  336. _M_owner = __id;
  337. ++_M_count;
  338. return true;
  339. }
  340. template<typename _Rep, typename _Period>
  341. bool
  342. try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
  343. {
  344. auto __id = this_thread::get_id();
  345. _Can_lock __can_lock{this, __id};
  346. unique_lock<mutex> __lk(_M_mut);
  347. if (!_M_cv.wait_for(__lk, __rtime, __can_lock))
  348. return false;
  349. if (_M_count == -1u)
  350. return false;
  351. _M_owner = __id;
  352. ++_M_count;
  353. return true;
  354. }
  355. template<typename _Clock, typename _Duration>
  356. bool
  357. try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
  358. {
  359. auto __id = this_thread::get_id();
  360. _Can_lock __can_lock{this, __id};
  361. unique_lock<mutex> __lk(_M_mut);
  362. if (!_M_cv.wait_until(__lk, __atime, __can_lock))
  363. return false;
  364. if (_M_count == -1u)
  365. return false;
  366. _M_owner = __id;
  367. ++_M_count;
  368. return true;
  369. }
  370. void
  371. unlock()
  372. {
  373. lock_guard<mutex> __lk(_M_mut);
  374. __glibcxx_assert( _M_owner == this_thread::get_id() );
  375. __glibcxx_assert( _M_count > 0 );
  376. if (--_M_count == 0)
  377. {
  378. _M_owner = {};
  379. _M_cv.notify_one();
  380. }
  381. }
  382. };
  383. #endif
  384. #endif // _GLIBCXX_HAS_GTHREADS
  385. template<typename _Lock>
  386. inline unique_lock<_Lock>
  387. __try_to_lock(_Lock& __l)
  388. { return unique_lock<_Lock>{__l, try_to_lock}; }
  389. template<int _Idx, bool _Continue = true>
  390. struct __try_lock_impl
  391. {
  392. template<typename... _Lock>
  393. static void
  394. __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
  395. {
  396. __idx = _Idx;
  397. auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
  398. if (__lock.owns_lock())
  399. {
  400. constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
  401. using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
  402. __try_locker::__do_try_lock(__locks, __idx);
  403. if (__idx == -1)
  404. __lock.release();
  405. }
  406. }
  407. };
  408. template<int _Idx>
  409. struct __try_lock_impl<_Idx, false>
  410. {
  411. template<typename... _Lock>
  412. static void
  413. __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
  414. {
  415. __idx = _Idx;
  416. auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
  417. if (__lock.owns_lock())
  418. {
  419. __idx = -1;
  420. __lock.release();
  421. }
  422. }
  423. };
  424. /** @brief Generic try_lock.
  425. * @param __l1 Meets Mutex requirements (try_lock() may throw).
  426. * @param __l2 Meets Mutex requirements (try_lock() may throw).
  427. * @param __l3 Meets Mutex requirements (try_lock() may throw).
  428. * @return Returns -1 if all try_lock() calls return true. Otherwise returns
  429. * a 0-based index corresponding to the argument that returned false.
  430. * @post Either all arguments are locked, or none will be.
  431. *
  432. * Sequentially calls try_lock() on each argument.
  433. */
  434. template<typename _Lock1, typename _Lock2, typename... _Lock3>
  435. int
  436. try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
  437. {
  438. int __idx;
  439. auto __locks = std::tie(__l1, __l2, __l3...);
  440. __try_lock_impl<0>::__do_try_lock(__locks, __idx);
  441. return __idx;
  442. }
  443. /** @brief Generic lock.
  444. * @param __l1 Meets Mutex requirements (try_lock() may throw).
  445. * @param __l2 Meets Mutex requirements (try_lock() may throw).
  446. * @param __l3 Meets Mutex requirements (try_lock() may throw).
  447. * @throw An exception thrown by an argument's lock() or try_lock() member.
  448. * @post All arguments are locked.
  449. *
  450. * All arguments are locked via a sequence of calls to lock(), try_lock()
  451. * and unlock(). If the call exits via an exception any locks that were
  452. * obtained will be released.
  453. */
  454. template<typename _L1, typename _L2, typename... _L3>
  455. void
  456. lock(_L1& __l1, _L2& __l2, _L3&... __l3)
  457. {
  458. while (true)
  459. {
  460. using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
  461. unique_lock<_L1> __first(__l1);
  462. int __idx;
  463. auto __locks = std::tie(__l2, __l3...);
  464. __try_locker::__do_try_lock(__locks, __idx);
  465. if (__idx == -1)
  466. {
  467. __first.release();
  468. return;
  469. }
  470. }
  471. }
  472. #ifdef _GLIBCXX_HAS_GTHREADS
  473. /// once_flag
  474. struct once_flag
  475. {
  476. private:
  477. typedef __gthread_once_t __native_type;
  478. __native_type _M_once = __GTHREAD_ONCE_INIT;
  479. public:
  480. /// Constructor
  481. constexpr once_flag() noexcept = default;
  482. /// Deleted copy constructor
  483. once_flag(const once_flag&) = delete;
  484. /// Deleted assignment operator
  485. once_flag& operator=(const once_flag&) = delete;
  486. template<typename _Callable, typename... _Args>
  487. friend void
  488. call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
  489. };
  490. #ifdef _GLIBCXX_HAVE_TLS
  491. extern __thread void* __once_callable;
  492. extern __thread void (*__once_call)();
  493. template<typename _Callable>
  494. inline void
  495. __once_call_impl()
  496. {
  497. (*(_Callable*)__once_callable)();
  498. }
  499. #else
  500. extern function<void()> __once_functor;
  501. extern void
  502. __set_once_functor_lock_ptr(unique_lock<mutex>*);
  503. extern mutex&
  504. __get_once_mutex();
  505. #endif
  506. extern "C" void __once_proxy(void);
  507. /// call_once
  508. template<typename _Callable, typename... _Args>
  509. void
  510. call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
  511. {
  512. #ifdef _GLIBCXX_HAVE_TLS
  513. auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
  514. std::forward<_Args>(__args)...);
  515. __once_callable = std::__addressof(__bound_functor);
  516. __once_call = &__once_call_impl<decltype(__bound_functor)>;
  517. #else
  518. unique_lock<mutex> __functor_lock(__get_once_mutex());
  519. auto __callable = std::__bind_simple(std::forward<_Callable>(__f),
  520. std::forward<_Args>(__args)...);
  521. __once_functor = [&]() { __callable(); };
  522. __set_once_functor_lock_ptr(&__functor_lock);
  523. #endif
  524. int __e = __gthread_once(&__once._M_once, &__once_proxy);
  525. #ifndef _GLIBCXX_HAVE_TLS
  526. if (__functor_lock)
  527. __set_once_functor_lock_ptr(0);
  528. #endif
  529. if (__e)
  530. __throw_system_error(__e);
  531. }
  532. #endif // _GLIBCXX_HAS_GTHREADS
  533. // @} group mutexes
  534. _GLIBCXX_END_NAMESPACE_VERSION
  535. } // namespace
  536. #endif // _GLIBCXX_USE_C99_STDINT_TR1
  537. #endif // C++11
  538. #endif // _GLIBCXX_MUTEX