2017-12-08 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libstdc++-v3 / include / std / mutex
blob50420ee22d4256ffc2451c8f4254f256a99a6a5a
1 // <mutex> -*- C++ -*-
3 // Copyright (C) 2003-2017 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file include/mutex
26  *  This is a Standard C++ Library header.
27  */
29 #ifndef _GLIBCXX_MUTEX
30 #define _GLIBCXX_MUTEX 1
32 #pragma GCC system_header
34 #if __cplusplus < 201103L
35 # include <bits/c++0x_warning.h>
36 #else
38 #include <tuple>
39 #include <chrono>
40 #include <exception>
41 #include <type_traits>
42 #include <system_error>
43 #include <bits/std_mutex.h>
44 #if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
45 # include <condition_variable>
46 # include <thread>
47 #endif
48 #ifndef _GLIBCXX_HAVE_TLS
49 # include <bits/std_function.h>
50 #endif
52 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
54 namespace std _GLIBCXX_VISIBILITY(default)
56 _GLIBCXX_BEGIN_NAMESPACE_VERSION
58   /**
59    * @ingroup mutexes
60    * @{
61    */
63 #ifdef _GLIBCXX_HAS_GTHREADS
65   // Common base class for std::recursive_mutex and std::recursive_timed_mutex
66   class __recursive_mutex_base
67   {
68   protected:
69     typedef __gthread_recursive_mutex_t         __native_type;
71     __recursive_mutex_base(const __recursive_mutex_base&) = delete;
72     __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
74 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
75     __native_type  _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
77     __recursive_mutex_base() = default;
78 #else
79     __native_type  _M_mutex;
81     __recursive_mutex_base()
82     {
83       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
84       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
85     }
87     ~__recursive_mutex_base()
88     { __gthread_recursive_mutex_destroy(&_M_mutex); }
89 #endif
90   };
92   /// The standard recursive mutex type.
93   class recursive_mutex : private __recursive_mutex_base
94   {
95   public:
96     typedef __native_type*                      native_handle_type;
98     recursive_mutex() = default;
99     ~recursive_mutex() = default;
101     recursive_mutex(const recursive_mutex&) = delete;
102     recursive_mutex& operator=(const recursive_mutex&) = delete;
104     void
105     lock()
106     {
107       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
109       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
110       if (__e)
111         __throw_system_error(__e);
112     }
114     bool
115     try_lock() noexcept
116     {
117       // XXX EINVAL, EAGAIN, EBUSY
118       return !__gthread_recursive_mutex_trylock(&_M_mutex);
119     }
121     void
122     unlock()
123     {
124       // XXX EINVAL, EAGAIN, EBUSY
125       __gthread_recursive_mutex_unlock(&_M_mutex);
126     }
128     native_handle_type
129     native_handle() noexcept
130     { return &_M_mutex; }
131   };
133 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
134   template<typename _Derived>
135     class __timed_mutex_impl
136     {
137     protected:
138       typedef chrono::high_resolution_clock     __clock_t;
140       template<typename _Rep, typename _Period>
141         bool
142         _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
143         {
144           using chrono::steady_clock;
145           auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
146           if (ratio_greater<steady_clock::period, _Period>())
147             ++__rt;
148           return _M_try_lock_until(steady_clock::now() + __rt);
149         }
151       template<typename _Duration>
152         bool
153         _M_try_lock_until(const chrono::time_point<__clock_t,
154                                                    _Duration>& __atime)
155         {
156           auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
157           auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
159           __gthread_time_t __ts = {
160             static_cast<std::time_t>(__s.time_since_epoch().count()),
161             static_cast<long>(__ns.count())
162           };
164           return static_cast<_Derived*>(this)->_M_timedlock(__ts);
165         }
167       template<typename _Clock, typename _Duration>
168         bool
169         _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
170         {
171           auto __rtime = __atime - _Clock::now();
172           return _M_try_lock_until(__clock_t::now() + __rtime);
173         }
174     };
176   /// The standard timed mutex type.
177   class timed_mutex
178   : private __mutex_base, public __timed_mutex_impl<timed_mutex>
179   {
180   public:
181     typedef __native_type*                      native_handle_type;
183     timed_mutex() = default;
184     ~timed_mutex() = default;
186     timed_mutex(const timed_mutex&) = delete;
187     timed_mutex& operator=(const timed_mutex&) = delete;
189     void
190     lock()
191     {
192       int __e = __gthread_mutex_lock(&_M_mutex);
194       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
195       if (__e)
196         __throw_system_error(__e);
197     }
199     bool
200     try_lock() noexcept
201     {
202       // XXX EINVAL, EAGAIN, EBUSY
203       return !__gthread_mutex_trylock(&_M_mutex);
204     }
206     template <class _Rep, class _Period>
207       bool
208       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
209       { return _M_try_lock_for(__rtime); }
211     template <class _Clock, class _Duration>
212       bool
213       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
214       { return _M_try_lock_until(__atime); }
216     void
217     unlock()
218     {
219       // XXX EINVAL, EAGAIN, EBUSY
220       __gthread_mutex_unlock(&_M_mutex);
221     }
223     native_handle_type
224     native_handle() noexcept
225     { return &_M_mutex; }
227     private:
228       friend class __timed_mutex_impl<timed_mutex>;
230       bool
231       _M_timedlock(const __gthread_time_t& __ts)
232       { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
233   };
235   /// recursive_timed_mutex
236   class recursive_timed_mutex
237   : private __recursive_mutex_base,
238     public __timed_mutex_impl<recursive_timed_mutex>
239   {
240   public:
241     typedef __native_type*                      native_handle_type;
243     recursive_timed_mutex() = default;
244     ~recursive_timed_mutex() = default;
246     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
247     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
249     void
250     lock()
251     {
252       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
254       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
255       if (__e)
256         __throw_system_error(__e);
257     }
259     bool
260     try_lock() noexcept
261     {
262       // XXX EINVAL, EAGAIN, EBUSY
263       return !__gthread_recursive_mutex_trylock(&_M_mutex);
264     }
266     template <class _Rep, class _Period>
267       bool
268       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
269       { return _M_try_lock_for(__rtime); }
271     template <class _Clock, class _Duration>
272       bool
273       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
274       { return _M_try_lock_until(__atime); }
276     void
277     unlock()
278     {
279       // XXX EINVAL, EAGAIN, EBUSY
280       __gthread_recursive_mutex_unlock(&_M_mutex);
281     }
283     native_handle_type
284     native_handle() noexcept
285     { return &_M_mutex; }
287     private:
288       friend class __timed_mutex_impl<recursive_timed_mutex>;
290       bool
291       _M_timedlock(const __gthread_time_t& __ts)
292       { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
293   };
295 #else // !_GTHREAD_USE_MUTEX_TIMEDLOCK
297   /// timed_mutex
298   class timed_mutex
299   {
300     mutex               _M_mut;
301     condition_variable  _M_cv;
302     bool                _M_locked = false;
304   public:
306     timed_mutex() = default;
307     ~timed_mutex() { __glibcxx_assert( !_M_locked ); }
309     timed_mutex(const timed_mutex&) = delete;
310     timed_mutex& operator=(const timed_mutex&) = delete;
312     void
313     lock()
314     {
315       unique_lock<mutex> __lk(_M_mut);
316       _M_cv.wait(__lk, [&]{ return !_M_locked; });
317       _M_locked = true;
318     }
320     bool
321     try_lock()
322     {
323       lock_guard<mutex> __lk(_M_mut);
324       if (_M_locked)
325         return false;
326       _M_locked = true;
327       return true;
328     }
330     template<typename _Rep, typename _Period>
331       bool
332       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
333       {
334         unique_lock<mutex> __lk(_M_mut);
335         if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
336           return false;
337         _M_locked = true;
338         return true;
339       }
341     template<typename _Clock, typename _Duration>
342       bool
343       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
344       {
345         unique_lock<mutex> __lk(_M_mut);
346         if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
347           return false;
348         _M_locked = true;
349         return true;
350       }
352     void
353     unlock()
354     {
355       lock_guard<mutex> __lk(_M_mut);
356       __glibcxx_assert( _M_locked );
357       _M_locked = false;
358       _M_cv.notify_one();
359     }
360   };
362   /// recursive_timed_mutex
363   class recursive_timed_mutex
364   {
365     mutex               _M_mut;
366     condition_variable  _M_cv;
367     thread::id          _M_owner;
368     unsigned            _M_count = 0;
370     // Predicate type that tests whether the current thread can lock a mutex.
371     struct _Can_lock
372     {
373       // Returns true if the mutex is unlocked or is locked by _M_caller.
374       bool
375       operator()() const noexcept
376       { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; }
378       const recursive_timed_mutex* _M_mx;
379       thread::id _M_caller;
380     };
382   public:
384     recursive_timed_mutex() = default;
385     ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
387     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
388     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
390     void
391     lock()
392     {
393       auto __id = this_thread::get_id();
394       _Can_lock __can_lock{this, __id};
395       unique_lock<mutex> __lk(_M_mut);
396       _M_cv.wait(__lk, __can_lock);
397       if (_M_count == -1u)
398         __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3
399       _M_owner = __id;
400       ++_M_count;
401     }
403     bool
404     try_lock()
405     {
406       auto __id = this_thread::get_id();
407       _Can_lock __can_lock{this, __id};
408       lock_guard<mutex> __lk(_M_mut);
409       if (!__can_lock())
410         return false;
411       if (_M_count == -1u)
412         return false;
413       _M_owner = __id;
414       ++_M_count;
415       return true;
416     }
418     template<typename _Rep, typename _Period>
419       bool
420       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
421       {
422         auto __id = this_thread::get_id();
423         _Can_lock __can_lock{this, __id};
424         unique_lock<mutex> __lk(_M_mut);
425         if (!_M_cv.wait_for(__lk, __rtime, __can_lock))
426           return false;
427         if (_M_count == -1u)
428           return false;
429         _M_owner = __id;
430         ++_M_count;
431         return true;
432       }
434     template<typename _Clock, typename _Duration>
435       bool
436       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
437       {
438         auto __id = this_thread::get_id();
439         _Can_lock __can_lock{this, __id};
440         unique_lock<mutex> __lk(_M_mut);
441         if (!_M_cv.wait_until(__lk, __atime, __can_lock))
442           return false;
443         if (_M_count == -1u)
444           return false;
445         _M_owner = __id;
446         ++_M_count;
447         return true;
448       }
450     void
451     unlock()
452     {
453       lock_guard<mutex> __lk(_M_mut);
454       __glibcxx_assert( _M_owner == this_thread::get_id() );
455       __glibcxx_assert( _M_count > 0 );
456       if (--_M_count == 0)
457         {
458           _M_owner = {};
459           _M_cv.notify_one();
460         }
461     }
462   };
464 #endif
465 #endif // _GLIBCXX_HAS_GTHREADS
467   template<typename _Lock>
468     inline unique_lock<_Lock>
469     __try_to_lock(_Lock& __l)
470     { return unique_lock<_Lock>{__l, try_to_lock}; }
472   template<int _Idx, bool _Continue = true>
473     struct __try_lock_impl
474     {
475       template<typename... _Lock>
476         static void
477         __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
478         {
479           __idx = _Idx;
480           auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
481           if (__lock.owns_lock())
482             {
483               constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
484               using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
485               __try_locker::__do_try_lock(__locks, __idx);
486               if (__idx == -1)
487                 __lock.release();
488             }
489         }
490     };
492   template<int _Idx>
493     struct __try_lock_impl<_Idx, false>
494     {
495       template<typename... _Lock>
496         static void
497         __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
498         {
499           __idx = _Idx;
500           auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
501           if (__lock.owns_lock())
502             {
503               __idx = -1;
504               __lock.release();
505             }
506         }
507     };
509   /** @brief Generic try_lock.
510    *  @param __l1 Meets Lockable requirements (try_lock() may throw).
511    *  @param __l2 Meets Lockable requirements (try_lock() may throw).
512    *  @param __l3 Meets Lockable requirements (try_lock() may throw).
513    *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
514    *          a 0-based index corresponding to the argument that returned false.
515    *  @post Either all arguments are locked, or none will be.
516    *
517    *  Sequentially calls try_lock() on each argument.
518    */
519   template<typename _Lock1, typename _Lock2, typename... _Lock3>
520     int
521     try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
522     {
523       int __idx;
524       auto __locks = std::tie(__l1, __l2, __l3...);
525       __try_lock_impl<0>::__do_try_lock(__locks, __idx);
526       return __idx;
527     }
529   /** @brief Generic lock.
530    *  @param __l1 Meets Lockable requirements (try_lock() may throw).
531    *  @param __l2 Meets Lockable requirements (try_lock() may throw).
532    *  @param __l3 Meets Lockable requirements (try_lock() may throw).
533    *  @throw An exception thrown by an argument's lock() or try_lock() member.
534    *  @post All arguments are locked.
535    *
536    *  All arguments are locked via a sequence of calls to lock(), try_lock()
537    *  and unlock().  If the call exits via an exception any locks that were
538    *  obtained will be released.
539    */
540   template<typename _L1, typename _L2, typename... _L3>
541     void
542     lock(_L1& __l1, _L2& __l2, _L3&... __l3)
543     {
544       while (true)
545         {
546           using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
547           unique_lock<_L1> __first(__l1);
548           int __idx;
549           auto __locks = std::tie(__l2, __l3...);
550           __try_locker::__do_try_lock(__locks, __idx);
551           if (__idx == -1)
552             {
553               __first.release();
554               return;
555             }
556         }
557     }
559 #if __cplusplus >= 201703L
560 #define __cpp_lib_scoped_lock 201703
561   /** @brief A scoped lock type for multiple lockable objects.
562    *
563    * A scoped_lock controls mutex ownership within a scope, releasing
564    * ownership in the destructor.
565    */
566   template<typename... _MutexTypes>
567     class scoped_lock
568     {
569     public:
570       explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...))
571       { std::lock(__m...); }
573       explicit scoped_lock(adopt_lock_t, _MutexTypes&... __m) noexcept
574       : _M_devices(std::tie(__m...))
575       { } // calling thread owns mutex
577       ~scoped_lock()
578       {
579         std::apply([](_MutexTypes&... __m) {
580           char __i[] __attribute__((__unused__)) = { (__m.unlock(), 0)... };
581         }, _M_devices);
582       }
584       scoped_lock(const scoped_lock&) = delete;
585       scoped_lock& operator=(const scoped_lock&) = delete;
587     private:
588       tuple<_MutexTypes&...> _M_devices;
589     };
591   template<>
592     class scoped_lock<>
593     {
594     public:
595       explicit scoped_lock() = default;
596       explicit scoped_lock(adopt_lock_t) noexcept { }
597       ~scoped_lock() = default;
599       scoped_lock(const scoped_lock&) = delete;
600       scoped_lock& operator=(const scoped_lock&) = delete;
601     };
603   template<typename _Mutex>
604     class scoped_lock<_Mutex>
605     {
606     public:
607       using mutex_type = _Mutex;
609       explicit scoped_lock(mutex_type& __m) : _M_device(__m)
610       { _M_device.lock(); }
612       explicit scoped_lock(adopt_lock_t, mutex_type& __m) noexcept
613       : _M_device(__m)
614       { } // calling thread owns mutex
616       ~scoped_lock()
617       { _M_device.unlock(); }
619       scoped_lock(const scoped_lock&) = delete;
620       scoped_lock& operator=(const scoped_lock&) = delete;
622     private:
623       mutex_type&  _M_device;
624     };
625 #endif // C++17
627 #ifdef _GLIBCXX_HAS_GTHREADS
628   /// once_flag
629   struct once_flag
630   {
631   private:
632     typedef __gthread_once_t __native_type;
633     __native_type  _M_once = __GTHREAD_ONCE_INIT;
635   public:
636     /// Constructor
637     constexpr once_flag() noexcept = default;
639     /// Deleted copy constructor
640     once_flag(const once_flag&) = delete;
641     /// Deleted assignment operator
642     once_flag& operator=(const once_flag&) = delete;
644     template<typename _Callable, typename... _Args>
645       friend void
646       call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
647   };
649 #ifdef _GLIBCXX_HAVE_TLS
650   extern __thread void* __once_callable;
651   extern __thread void (*__once_call)();
652 #else
653   extern function<void()> __once_functor;
655   extern void
656   __set_once_functor_lock_ptr(unique_lock<mutex>*);
658   extern mutex&
659   __get_once_mutex();
660 #endif
662   extern "C" void __once_proxy(void);
664   /// call_once
665   template<typename _Callable, typename... _Args>
666     void
667     call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
668     {
669       // _GLIBCXX_RESOLVE_LIB_DEFECTS
670       // 2442. call_once() shouldn't DECAY_COPY()
671       auto __callable = [&] {
672           std::__invoke(std::forward<_Callable>(__f),
673                         std::forward<_Args>(__args)...);
674       };
675 #ifdef _GLIBCXX_HAVE_TLS
676       __once_callable = std::__addressof(__callable);
677       __once_call = []{ (*(decltype(__callable)*)__once_callable)(); };
678 #else
679       unique_lock<mutex> __functor_lock(__get_once_mutex());
680       __once_functor = __callable;
681       __set_once_functor_lock_ptr(&__functor_lock);
682 #endif
684       int __e = __gthread_once(&__once._M_once, &__once_proxy);
686 #ifndef _GLIBCXX_HAVE_TLS
687       if (__functor_lock)
688         __set_once_functor_lock_ptr(0);
689 #endif
691 #ifdef __clang_analyzer__
692       // PR libstdc++/82481
693       __once_callable = nullptr;
694       __once_call = nullptr;
695 #endif
697       if (__e)
698         __throw_system_error(__e);
699     }
700 #endif // _GLIBCXX_HAS_GTHREADS
702   // @} group mutexes
703 _GLIBCXX_END_NAMESPACE_VERSION
704 } // namespace
705 #endif // _GLIBCXX_USE_C99_STDINT_TR1
707 #endif // C++11
709 #endif // _GLIBCXX_MUTEX