2015-09-02 Sebastian Huber <sebastian.huber@embedded-brains.de>
[official-gcc.git] / libstdc++-v3 / include / std / mutex
blob790508c65c235300cffc593b974acf79d02ef4dd
1 // <mutex> -*- C++ -*-
3 // Copyright (C) 2003-2015 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 <functional>
43 #include <system_error>
44 #include <bits/functexcept.h>
45 #include <bits/gthr.h>
46 #include <bits/move.h> // for std::swap
47 #include <bits/cxxabi_forced.h>
49 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
51 namespace std _GLIBCXX_VISIBILITY(default)
53 _GLIBCXX_BEGIN_NAMESPACE_VERSION
55 #ifdef _GLIBCXX_HAS_GTHREADS
56   // Common base class for std::mutex and std::timed_mutex
57   class __mutex_base
58   {
59   protected:
60     typedef __gthread_mutex_t                   __native_type;
62 #ifdef __GTHREAD_MUTEX_INIT
63     __native_type  _M_mutex = __GTHREAD_MUTEX_INIT;
65     constexpr __mutex_base() noexcept = default;
66 #else
67     __native_type  _M_mutex;
69     __mutex_base() noexcept
70     {
71       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
72       __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
73     }
75     ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }
76 #endif
78     __mutex_base(const __mutex_base&) = delete;
79     __mutex_base& operator=(const __mutex_base&) = delete;
80   };
82   // Common base class for std::recursive_mutex and std::recursive_timed_mutex
83   class __recursive_mutex_base
84   {
85   protected:
86     typedef __gthread_recursive_mutex_t         __native_type;
88     __recursive_mutex_base(const __recursive_mutex_base&) = delete;
89     __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
91 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
92     __native_type  _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
94     __recursive_mutex_base() = default;
95 #else
96     __native_type  _M_mutex;
98     __recursive_mutex_base()
99     {
100       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
101       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
102     }
104     ~__recursive_mutex_base()
105     { __gthread_recursive_mutex_destroy(&_M_mutex); }
106 #endif
107   };
109   /**
110    * @defgroup mutexes Mutexes
111    * @ingroup concurrency
112    *
113    * Classes for mutex support.
114    * @{
115    */
117   /// mutex
118   class mutex : private __mutex_base
119   {
120   public:
121     typedef __native_type*                      native_handle_type;
123 #ifdef __GTHREAD_MUTEX_INIT
124     constexpr
125 #endif
126     mutex() noexcept = default;
127     ~mutex() = default;
129     mutex(const mutex&) = delete;
130     mutex& operator=(const mutex&) = delete;
132     void
133     lock()
134     {
135       int __e = __gthread_mutex_lock(&_M_mutex);
137       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
138       if (__e)
139         __throw_system_error(__e);
140     }
142     bool
143     try_lock() noexcept
144     {
145       // XXX EINVAL, EAGAIN, EBUSY
146       return !__gthread_mutex_trylock(&_M_mutex);
147     }
149     void
150     unlock()
151     {
152       // XXX EINVAL, EAGAIN, EPERM
153       __gthread_mutex_unlock(&_M_mutex);
154     }
156     native_handle_type
157     native_handle()
158     { return &_M_mutex; }
159   };
161   /// recursive_mutex
162   class recursive_mutex : private __recursive_mutex_base
163   {
164   public:
165     typedef __native_type*                      native_handle_type;
167     recursive_mutex() = default;
168     ~recursive_mutex() = default;
170     recursive_mutex(const recursive_mutex&) = delete;
171     recursive_mutex& operator=(const recursive_mutex&) = delete;
173     void
174     lock()
175     {
176       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
178       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
179       if (__e)
180         __throw_system_error(__e);
181     }
183     bool
184     try_lock() noexcept
185     {
186       // XXX EINVAL, EAGAIN, EBUSY
187       return !__gthread_recursive_mutex_trylock(&_M_mutex);
188     }
190     void
191     unlock()
192     {
193       // XXX EINVAL, EAGAIN, EBUSY
194       __gthread_recursive_mutex_unlock(&_M_mutex);
195     }
197     native_handle_type
198     native_handle()
199     { return &_M_mutex; }
200   };
202 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
203   template<typename _Derived>
204     class __timed_mutex_impl
205     {
206     protected:
207       typedef chrono::high_resolution_clock     __clock_t;
209       template<typename _Rep, typename _Period>
210         bool
211         _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
212         {
213           using chrono::steady_clock;
214           auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
215           if (ratio_greater<steady_clock::period, _Period>())
216             ++__rt;
217           return _M_try_lock_until(steady_clock::now() + __rt);
218         }
220       template<typename _Duration>
221         bool
222         _M_try_lock_until(const chrono::time_point<__clock_t,
223                                                    _Duration>& __atime)
224         {
225           auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
226           auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
228           __gthread_time_t __ts = {
229             static_cast<std::time_t>(__s.time_since_epoch().count()),
230             static_cast<long>(__ns.count())
231           };
233           return static_cast<_Derived*>(this)->_M_timedlock(__ts);
234         }
236       template<typename _Clock, typename _Duration>
237         bool
238         _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
239         {
240           auto __rtime = __atime - _Clock::now();
241           return _M_try_lock_until(__clock_t::now() + __rtime);
242         }
243     };
245   /// timed_mutex
246   class timed_mutex
247   : private __mutex_base, public __timed_mutex_impl<timed_mutex>
248   {
249   public:
250     typedef __native_type*                      native_handle_type;
252     timed_mutex() = default;
253     ~timed_mutex() = default;
255     timed_mutex(const timed_mutex&) = delete;
256     timed_mutex& operator=(const timed_mutex&) = delete;
258     void
259     lock()
260     {
261       int __e = __gthread_mutex_lock(&_M_mutex);
263       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
264       if (__e)
265         __throw_system_error(__e);
266     }
268     bool
269     try_lock() noexcept
270     {
271       // XXX EINVAL, EAGAIN, EBUSY
272       return !__gthread_mutex_trylock(&_M_mutex);
273     }
275     template <class _Rep, class _Period>
276       bool
277       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
278       { return _M_try_lock_for(__rtime); }
280     template <class _Clock, class _Duration>
281       bool
282       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
283       { return _M_try_lock_until(__atime); }
285     void
286     unlock()
287     {
288       // XXX EINVAL, EAGAIN, EBUSY
289       __gthread_mutex_unlock(&_M_mutex);
290     }
292     native_handle_type
293     native_handle()
294     { return &_M_mutex; }
296     private:
297       friend class __timed_mutex_impl<timed_mutex>;
299       bool
300       _M_timedlock(const __gthread_time_t& __ts)
301       { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
302   };
304   /// recursive_timed_mutex
305   class recursive_timed_mutex
306   : private __recursive_mutex_base,
307     public __timed_mutex_impl<recursive_timed_mutex>
308   {
309   public:
310     typedef __native_type*                      native_handle_type;
312     recursive_timed_mutex() = default;
313     ~recursive_timed_mutex() = default;
315     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
316     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
318     void
319     lock()
320     {
321       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
323       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
324       if (__e)
325         __throw_system_error(__e);
326     }
328     bool
329     try_lock() noexcept
330     {
331       // XXX EINVAL, EAGAIN, EBUSY
332       return !__gthread_recursive_mutex_trylock(&_M_mutex);
333     }
335     template <class _Rep, class _Period>
336       bool
337       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
338       { return _M_try_lock_for(__rtime); }
340     template <class _Clock, class _Duration>
341       bool
342       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
343       { return _M_try_lock_until(__atime); }
345     void
346     unlock()
347     {
348       // XXX EINVAL, EAGAIN, EBUSY
349       __gthread_recursive_mutex_unlock(&_M_mutex);
350     }
352     native_handle_type
353     native_handle()
354     { return &_M_mutex; }
356     private:
357       friend class __timed_mutex_impl<recursive_timed_mutex>;
359       bool
360       _M_timedlock(const __gthread_time_t& __ts)
361       { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
362   };
363 #endif
364 #endif // _GLIBCXX_HAS_GTHREADS
366   /// Do not acquire ownership of the mutex.
367   struct defer_lock_t { };
369   /// Try to acquire ownership of the mutex without blocking.
370   struct try_to_lock_t { };
372   /// Assume the calling thread has already obtained mutex ownership
373   /// and manage it.
374   struct adopt_lock_t { };
376   constexpr defer_lock_t        defer_lock { };
377   constexpr try_to_lock_t       try_to_lock { };
378   constexpr adopt_lock_t        adopt_lock { };
380   /// @brief  Scoped lock idiom.
381   // Acquire the mutex here with a constructor call, then release with
382   // the destructor call in accordance with RAII style.
383   template<typename _Mutex>
384     class lock_guard
385     {
386     public:
387       typedef _Mutex mutex_type;
389       explicit lock_guard(mutex_type& __m) : _M_device(__m)
390       { _M_device.lock(); }
392       lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m)
393       { } // calling thread owns mutex
395       ~lock_guard()
396       { _M_device.unlock(); }
398       lock_guard(const lock_guard&) = delete;
399       lock_guard& operator=(const lock_guard&) = delete;
401     private:
402       mutex_type&  _M_device;
403     };
405   /// unique_lock
406   template<typename _Mutex>
407     class unique_lock
408     {
409     public:
410       typedef _Mutex mutex_type;
412       unique_lock() noexcept
413       : _M_device(0), _M_owns(false)
414       { }
416       explicit unique_lock(mutex_type& __m)
417       : _M_device(std::__addressof(__m)), _M_owns(false)
418       {
419         lock();
420         _M_owns = true;
421       }
423       unique_lock(mutex_type& __m, defer_lock_t) noexcept
424       : _M_device(std::__addressof(__m)), _M_owns(false)
425       { }
427       unique_lock(mutex_type& __m, try_to_lock_t)
428       : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
429       { }
431       unique_lock(mutex_type& __m, adopt_lock_t)
432       : _M_device(std::__addressof(__m)), _M_owns(true)
433       {
434         // XXX calling thread owns mutex
435       }
437       template<typename _Clock, typename _Duration>
438         unique_lock(mutex_type& __m,
439                     const chrono::time_point<_Clock, _Duration>& __atime)
440         : _M_device(std::__addressof(__m)),
441           _M_owns(_M_device->try_lock_until(__atime))
442         { }
444       template<typename _Rep, typename _Period>
445         unique_lock(mutex_type& __m,
446                     const chrono::duration<_Rep, _Period>& __rtime)
447         : _M_device(std::__addressof(__m)),
448           _M_owns(_M_device->try_lock_for(__rtime))
449         { }
451       ~unique_lock()
452       {
453         if (_M_owns)
454           unlock();
455       }
457       unique_lock(const unique_lock&) = delete;
458       unique_lock& operator=(const unique_lock&) = delete;
460       unique_lock(unique_lock&& __u) noexcept
461       : _M_device(__u._M_device), _M_owns(__u._M_owns)
462       {
463         __u._M_device = 0;
464         __u._M_owns = false;
465       }
467       unique_lock& operator=(unique_lock&& __u) noexcept
468       {
469         if(_M_owns)
470           unlock();
472         unique_lock(std::move(__u)).swap(*this);
474         __u._M_device = 0;
475         __u._M_owns = false;
477         return *this;
478       }
480       void
481       lock()
482       {
483         if (!_M_device)
484           __throw_system_error(int(errc::operation_not_permitted));
485         else if (_M_owns)
486           __throw_system_error(int(errc::resource_deadlock_would_occur));
487         else
488           {
489             _M_device->lock();
490             _M_owns = true;
491           }
492       }
494       bool
495       try_lock()
496       {
497         if (!_M_device)
498           __throw_system_error(int(errc::operation_not_permitted));
499         else if (_M_owns)
500           __throw_system_error(int(errc::resource_deadlock_would_occur));
501         else
502           {
503             _M_owns = _M_device->try_lock();
504             return _M_owns;
505           }
506       }
508       template<typename _Clock, typename _Duration>
509         bool
510         try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
511         {
512           if (!_M_device)
513             __throw_system_error(int(errc::operation_not_permitted));
514           else if (_M_owns)
515             __throw_system_error(int(errc::resource_deadlock_would_occur));
516           else
517             {
518               _M_owns = _M_device->try_lock_until(__atime);
519               return _M_owns;
520             }
521         }
523       template<typename _Rep, typename _Period>
524         bool
525         try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
526         {
527           if (!_M_device)
528             __throw_system_error(int(errc::operation_not_permitted));
529           else if (_M_owns)
530             __throw_system_error(int(errc::resource_deadlock_would_occur));
531           else
532             {
533               _M_owns = _M_device->try_lock_for(__rtime);
534               return _M_owns;
535             }
536          }
538       void
539       unlock()
540       {
541         if (!_M_owns)
542           __throw_system_error(int(errc::operation_not_permitted));
543         else if (_M_device)
544           {
545             _M_device->unlock();
546             _M_owns = false;
547           }
548       }
550       void
551       swap(unique_lock& __u) noexcept
552       {
553         std::swap(_M_device, __u._M_device);
554         std::swap(_M_owns, __u._M_owns);
555       }
557       mutex_type*
558       release() noexcept
559       {
560         mutex_type* __ret = _M_device;
561         _M_device = 0;
562         _M_owns = false;
563         return __ret;
564       }
566       bool
567       owns_lock() const noexcept
568       { return _M_owns; }
570       explicit operator bool() const noexcept
571       { return owns_lock(); }
573       mutex_type*
574       mutex() const noexcept
575       { return _M_device; }
577     private:
578       mutex_type*       _M_device;
579       bool              _M_owns; // XXX use atomic_bool
580     };
582   /// Swap overload for unique_lock objects.
583   template<typename _Mutex>
584     inline void
585     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
586     { __x.swap(__y); }
588   template<typename _Lock>
589     inline unique_lock<_Lock>
590     __try_to_lock(_Lock& __l)
591     { return unique_lock<_Lock>{__l, try_to_lock}; }
593   template<int _Idx, bool _Continue = true>
594     struct __try_lock_impl
595     {
596       template<typename... _Lock>
597         static void
598         __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
599         {
600           __idx = _Idx;
601           auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
602           if (__lock.owns_lock())
603             {
604               constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
605               using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
606               __try_locker::__do_try_lock(__locks, __idx);
607               if (__idx == -1)
608                 __lock.release();
609             }
610         }
611     };
613   template<int _Idx>
614     struct __try_lock_impl<_Idx, false>
615     {
616       template<typename... _Lock>
617         static void
618         __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
619         {
620           __idx = _Idx;
621           auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
622           if (__lock.owns_lock())
623             {
624               __idx = -1;
625               __lock.release();
626             }
627         }
628     };
630   /** @brief Generic try_lock.
631    *  @param __l1 Meets Mutex requirements (try_lock() may throw).
632    *  @param __l2 Meets Mutex requirements (try_lock() may throw).
633    *  @param __l3 Meets Mutex requirements (try_lock() may throw).
634    *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
635    *          a 0-based index corresponding to the argument that returned false.
636    *  @post Either all arguments are locked, or none will be.
637    *
638    *  Sequentially calls try_lock() on each argument.
639    */
640   template<typename _Lock1, typename _Lock2, typename... _Lock3>
641     int
642     try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
643     {
644       int __idx;
645       auto __locks = std::tie(__l1, __l2, __l3...);
646       __try_lock_impl<0>::__do_try_lock(__locks, __idx);
647       return __idx;
648     }
650   /** @brief Generic lock.
651    *  @param __l1 Meets Mutex requirements (try_lock() may throw).
652    *  @param __l2 Meets Mutex requirements (try_lock() may throw).
653    *  @param __l3 Meets Mutex requirements (try_lock() may throw).
654    *  @throw An exception thrown by an argument's lock() or try_lock() member.
655    *  @post All arguments are locked.
656    *
657    *  All arguments are locked via a sequence of calls to lock(), try_lock()
658    *  and unlock().  If the call exits via an exception any locks that were
659    *  obtained will be released.
660    */
661   template<typename _L1, typename _L2, typename... _L3>
662     void
663     lock(_L1& __l1, _L2& __l2, _L3&... __l3)
664     {
665       while (true)
666         {
667           using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
668           unique_lock<_L1> __first(__l1);
669           int __idx;
670           auto __locks = std::tie(__l2, __l3...);
671           __try_locker::__do_try_lock(__locks, __idx);
672           if (__idx == -1)
673             {
674               __first.release();
675               return;
676             }
677         }
678     }
680 #ifdef _GLIBCXX_HAS_GTHREADS
681   /// once_flag
682   struct once_flag
683   {
684   private:
685     typedef __gthread_once_t __native_type;
686     __native_type  _M_once = __GTHREAD_ONCE_INIT;
688   public:
689     /// Constructor
690     constexpr once_flag() noexcept = default;
692     /// Deleted copy constructor
693     once_flag(const once_flag&) = delete;
694     /// Deleted assignment operator
695     once_flag& operator=(const once_flag&) = delete;
697     template<typename _Callable, typename... _Args>
698       friend void
699       call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
700   };
702 #ifdef _GLIBCXX_HAVE_TLS
703   extern __thread void* __once_callable;
704   extern __thread void (*__once_call)();
706   template<typename _Callable>
707     inline void
708     __once_call_impl()
709     {
710       (*(_Callable*)__once_callable)();
711     }
712 #else
713   extern function<void()> __once_functor;
715   extern void
716   __set_once_functor_lock_ptr(unique_lock<mutex>*);
718   extern mutex&
719   __get_once_mutex();
720 #endif
722   extern "C" void __once_proxy(void);
724   /// call_once
725   template<typename _Callable, typename... _Args>
726     void
727     call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
728     {
729 #ifdef _GLIBCXX_HAVE_TLS
730       auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
731           std::forward<_Args>(__args)...);
732       __once_callable = std::__addressof(__bound_functor);
733       __once_call = &__once_call_impl<decltype(__bound_functor)>;
734 #else
735       unique_lock<mutex> __functor_lock(__get_once_mutex());
736       auto __callable = std::__bind_simple(std::forward<_Callable>(__f),
737           std::forward<_Args>(__args)...);
738       __once_functor = [&]() { __callable(); };
739       __set_once_functor_lock_ptr(&__functor_lock);
740 #endif
742       int __e = __gthread_once(&__once._M_once, &__once_proxy);
744 #ifndef _GLIBCXX_HAVE_TLS
745       if (__functor_lock)
746         __set_once_functor_lock_ptr(0);
747 #endif
749       if (__e)
750         __throw_system_error(__e);
751     }
752 #endif // _GLIBCXX_HAS_GTHREADS
754   // @} group mutexes
755 _GLIBCXX_END_NAMESPACE_VERSION
756 } // namespace
757 #endif // _GLIBCXX_USE_C99_STDINT_TR1
759 #endif // C++11
761 #endif // _GLIBCXX_MUTEX