OSDN Git Service

e4ceaf2aac893a83b3f3b3bbaa88dc06590a0f17
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / std / mutex
1 // <mutex> -*- C++ -*-
2
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License
18 // along with this library; see the file COPYING.  If not, write to
19 // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20 // Boston, MA 02110-1301, USA.
21
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction.  Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License.  This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
30
31 /** @file mutex
32  *  This is a Standard C++ Library header.
33  */
34
35 #ifndef _GLIBCXX_MUTEX
36 #define _GLIBCXX_MUTEX 1
37
38 #pragma GCC system_header
39
40 #ifndef __GXX_EXPERIMENTAL_CXX0X__
41 # include <c++0x_warning.h>
42 #else
43
44 #include <cstddef>
45 #include <chrono>
46 #include <exception>
47 #include <type_traits>
48 #include <functional>
49 #include <system_error>
50 #include <bits/functexcept.h>
51 #include <bits/gthr.h>
52 #include <bits/move.h> // for std::swap
53
54 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
55
56 namespace std
57 {
58   /// mutex
59   class mutex
60   {
61   public:
62     typedef __gthread_mutex_t* native_handle_type;
63
64     mutex()
65     {
66       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
67 #ifdef __GTHREAD_MUTEX_INIT
68       __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT;
69       _M_mutex = __tmp;
70 #else
71       __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
72 #endif
73     }
74
75     mutex(const mutex&) = delete;
76     mutex& operator=(const mutex&) = delete;
77
78     void
79     lock()
80     {
81       int __e = __gthread_mutex_lock(&_M_mutex);
82
83       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
84       if (__e)
85         __throw_system_error(__e);
86     }
87
88     bool
89     try_lock()
90     {
91       // XXX EINVAL, EAGAIN, EBUSY
92       return !__gthread_mutex_trylock(&_M_mutex);
93     }
94
95     void
96     unlock()
97     {
98       // XXX EINVAL, EAGAIN, EPERM
99       __gthread_mutex_unlock(&_M_mutex);
100     }
101
102     native_handle_type
103     native_handle()
104     { return &_M_mutex; }
105
106   private:
107     __gthread_mutex_t _M_mutex;
108   };
109
110   /// recursive_mutex
111   class recursive_mutex
112   {
113   public:
114     typedef __gthread_recursive_mutex_t* native_handle_type;
115
116     recursive_mutex()
117     {
118       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
119 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
120       __gthread_recursive_mutex_t __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
121       _M_mutex = __tmp;
122 #else
123       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
124 #endif
125     }
126
127     recursive_mutex(const recursive_mutex&) = delete;
128     recursive_mutex& operator=(const recursive_mutex&) = delete;
129
130     void
131     lock()
132     {
133       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
134
135       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
136       if (__e)
137         __throw_system_error(__e);
138     }
139
140     bool
141     try_lock()
142     {
143       // XXX EINVAL, EAGAIN, EBUSY
144       return !__gthread_recursive_mutex_trylock(&_M_mutex);
145     }
146
147     void
148     unlock()
149     {
150       // XXX EINVAL, EAGAIN, EBUSY
151       __gthread_recursive_mutex_unlock(&_M_mutex);
152     }
153
154     native_handle_type
155     native_handle()
156     { return &_M_mutex; }
157
158   private:
159     __gthread_recursive_mutex_t  _M_mutex;
160   };
161
162   /// timed_mutex
163   class timed_mutex
164   {  
165   public:
166     typedef __gthread_mutex_t* native_handle_type;
167
168     timed_mutex()
169     {
170 #ifdef __GTHREAD_MUTEX_INIT
171       __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT;
172       _M_mutex = __tmp;
173 #else
174       __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
175 #endif
176     }
177
178     timed_mutex(const timed_mutex&) = delete;
179     timed_mutex& operator=(const timed_mutex&) = delete;
180
181     void
182     lock()
183     {
184       int __e = __gthread_mutex_lock(&_M_mutex);
185
186       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
187       if (__e)
188         __throw_system_error(__e);
189     }
190
191     bool
192     try_lock()
193     {
194       // XXX EINVAL, EAGAIN, EBUSY
195       return !__gthread_mutex_trylock(&_M_mutex);
196     }
197
198     template <class _Rep, class _Period>
199       bool
200       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
201       { return __try_lock_for_impl(__rtime); }
202
203     template <class _Clock, class _Duration>
204       bool
205       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
206       { 
207         chrono::time_point<_Clock, chrono::seconds> __s =
208           chrono::time_point_cast<chrono::seconds>(__atime);
209
210         chrono::nanoseconds __ns =
211           chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
212
213         __gthread_time_t __ts = {
214           static_cast<std::time_t>(__s.time_since_epoch().count()),
215           static_cast<long>(__ns.count())
216         };
217
218         return !__gthread_mutex_timedlock(&_M_mutex, &__ts);    
219       }
220
221     void
222     unlock()
223     {
224       // XXX EINVAL, EAGAIN, EBUSY
225       __gthread_mutex_unlock(&_M_mutex);
226     }
227
228     native_handle_type
229     native_handle()
230     { return &_M_mutex; }
231     
232   private:
233     __gthread_mutex_t _M_mutex;
234     
235 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
236     typedef chrono::monotonic_clock __clock_t;
237 #else
238     typedef chrono::high_resolution_clock __clock_t;
239 #endif
240
241     template<typename _Rep, typename _Period>
242       typename enable_if<
243         ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
244       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
245       {
246         __clock_t::time_point __atime = __clock_t::now()
247           + chrono::duration_cast<__clock_t::duration>(__rtime);
248
249         return try_lock_until(__atime);
250       }
251
252     template <typename _Rep, typename _Period>
253       typename enable_if<
254         !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
255       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
256       {
257         __clock_t::time_point __atime = __clock_t::now()
258           + ++chrono::duration_cast<__clock_t::duration>(__rtime);
259
260         return try_lock_until(__atime);
261       }
262   };
263
264   /// recursive_timed_mutex
265   class recursive_timed_mutex
266   {
267   public:
268     typedef __gthread_recursive_mutex_t* native_handle_type;
269
270     recursive_timed_mutex()
271     {
272       // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
273 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
274       __gthread_recursive_mutex_t __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
275       _M_mutex = __tmp;
276 #else
277       __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
278 #endif
279     }
280
281     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
282     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
283
284     void
285     lock()
286     {
287       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
288
289       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
290       if (__e)
291         __throw_system_error(__e);
292     }
293
294     bool
295     try_lock()
296     {
297       // XXX EINVAL, EAGAIN, EBUSY
298       return !__gthread_recursive_mutex_trylock(&_M_mutex);
299     }
300
301     template <class _Rep, class _Period>
302       bool
303       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
304       { return __try_lock_for_impl(__rtime); }
305
306     template <class _Clock, class _Duration>
307       bool
308       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
309       { 
310         chrono::time_point<_Clock, chrono::seconds>  __s =
311           chrono::time_point_cast<chrono::seconds>(__atime);
312
313         chrono::nanoseconds __ns =
314           chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
315
316         __gthread_time_t __ts = {
317           static_cast<std::time_t>(__s.time_since_epoch().count()),
318           static_cast<long>(__ns.count())
319         };
320
321         return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts);
322       }
323
324     void
325     unlock()
326     {
327       // XXX EINVAL, EAGAIN, EBUSY
328       __gthread_recursive_mutex_unlock(&_M_mutex);
329     }
330
331     native_handle_type
332     native_handle()
333     { return &_M_mutex; }
334
335   private:
336     __gthread_recursive_mutex_t _M_mutex;
337
338 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
339     typedef chrono::monotonic_clock __clock_t;
340 #else
341     typedef chrono::high_resolution_clock __clock_t;
342 #endif
343
344     template<typename _Rep, typename _Period>
345       typename enable_if<
346         ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
347       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
348       {
349         __clock_t::time_point __atime = __clock_t::now()
350           + chrono::duration_cast<__clock_t::duration>(__rtime);
351
352         return try_lock_until(__atime);
353       }
354
355     template <typename _Rep, typename _Period>
356       typename enable_if<
357         !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
358       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
359       {
360         __clock_t::time_point __atime = __clock_t::now()
361           + ++chrono::duration_cast<__clock_t::duration>(__rtime);
362
363         return try_lock_until(__atime);
364       }
365   };
366
367   /// Do not acquire ownership of the mutex.
368   struct defer_lock_t { };
369
370   /// Try to acquire ownership of the mutex without blocking.
371   struct try_to_lock_t { };
372
373   /// Assume the calling thread has already obtained mutex ownership
374   /// and manage it.
375   struct adopt_lock_t { };
376
377   extern const defer_lock_t     defer_lock;
378   extern const try_to_lock_t    try_to_lock;
379   extern const adopt_lock_t     adopt_lock;
380
381   /// Thrown to indicate errors with lock operations.
382   class lock_error : public exception
383   {
384   public:
385     virtual const char*
386     what() const throw();
387   };
388
389   /// @brief  Scoped lock idiom.
390   // Acquire the mutex here with a constructor call, then release with
391   // the destructor call in accordance with RAII style.
392   template<typename _Mutex>
393     class lock_guard
394     {
395     public:
396       typedef _Mutex mutex_type;
397
398       explicit lock_guard(mutex_type& __m) : _M_device(__m)
399       { _M_device.lock(); }
400
401       lock_guard(mutex_type& __m, adopt_lock_t __a) : _M_device(__m)
402       { _M_device.lock(); }
403
404       ~lock_guard()
405       { _M_device.unlock(); }
406
407       lock_guard(const lock_guard&) = delete;
408       lock_guard& operator=(const lock_guard&) = delete;
409
410     private:
411       mutex_type&  _M_device;
412     };
413
414   /// unique_lock
415   template<typename _Mutex>
416     class unique_lock
417     {
418     public:
419       typedef _Mutex mutex_type;
420       
421       unique_lock()
422       : _M_device(0), _M_owns(false)
423       { }
424
425       explicit unique_lock(mutex_type& __m)
426       : _M_device(&__m), _M_owns(false)
427       {
428         lock();
429         _M_owns = true;
430       }
431
432       unique_lock(mutex_type& __m, defer_lock_t)
433       : _M_device(&__m), _M_owns(false)
434       { }
435
436       unique_lock(mutex_type& __m, try_to_lock_t)
437       : _M_device(&__m), _M_owns(_M_device->try_lock())
438       { }
439
440       unique_lock(mutex_type& __m, adopt_lock_t)
441       : _M_device(&__m), _M_owns(true)
442       {
443         // XXX calling thread owns mutex
444       }
445
446       template<typename _Clock, typename _Duration>
447         unique_lock(mutex_type& __m, 
448                     const chrono::time_point<_Clock, _Duration>& __atime)
449         : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
450         { }
451
452       template<typename _Rep, typename _Period>
453         unique_lock(mutex_type& __m, 
454                     const chrono::duration<_Rep, _Period>& __rtime)
455         : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
456         { }
457
458       ~unique_lock()
459       {
460         if (_M_owns)
461           unlock();
462       }
463
464       unique_lock(const unique_lock&) = delete;
465       unique_lock& operator=(const unique_lock&) = delete;
466
467       unique_lock(unique_lock&& __u)
468       : _M_device(__u._M_device), _M_owns(__u._M_owns)
469       {
470         __u._M_device = 0;
471         __u._M_owns = false;
472       }
473
474       unique_lock& operator=(unique_lock&& __u)
475       {
476         if(_M_owns)
477           unlock();
478         
479         unique_lock(std::move(__u)).swap(*this);
480
481         __u._M_device = 0;
482         __u._M_owns = false;
483         
484         return *this;
485       }
486
487       void
488       lock()
489       {
490         if (!_M_device)
491           __throw_system_error(posix_error::operation_not_permitted);
492         else if (_M_owns)
493           __throw_system_error(posix_error::resource_deadlock_would_occur);
494         else
495           {
496             _M_device->lock();
497             _M_owns = true;
498           }
499       }
500
501       bool
502       try_lock()
503       {
504         if (!_M_device)
505           __throw_system_error(posix_error::operation_not_permitted);
506         else if (_M_owns)
507           __throw_system_error(posix_error::resource_deadlock_would_occur);
508         else
509           {
510             _M_owns = _M_device->try_lock();        
511             return _M_owns;
512           }
513       }
514
515       template<typename _Clock, typename _Duration>
516         bool
517         try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
518         {
519           if (!_M_device)
520             __throw_system_error(posix_error::operation_not_permitted);
521           else if (_M_owns)
522             __throw_system_error(posix_error::resource_deadlock_would_occur);
523           else
524             {
525               _M_owns = _M_device->try_lock_until(__atime);
526               return _M_owns;
527             }
528         }
529       
530       template<typename _Rep, typename _Period>
531         bool
532         try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
533         {
534           if (!_M_device)
535             __throw_system_error(posix_error::operation_not_permitted);
536           else if (_M_owns)
537             __throw_system_error(posix_error::resource_deadlock_would_occur);
538           else
539             {
540               _M_owns = _M_device->try_lock_for(__rtime);
541               return _M_owns;
542             }
543          }
544
545       void
546       unlock()
547       {
548         if (!_M_owns)
549           __throw_system_error(posix_error::operation_not_permitted);
550         else if (_M_device)
551           {
552             _M_device->unlock();
553             _M_owns = false;
554           }
555       }
556       
557       void
558       swap(unique_lock&& __u)
559       {
560         std::swap(_M_device, __u._M_device);
561         std::swap(_M_owns, __u._M_owns);
562       }
563
564       mutex_type*
565       release()
566       {
567         mutex_type* __ret = _M_device;
568         _M_device = 0;
569         _M_owns = false;
570         return __ret;
571       }
572
573       bool
574       owns_lock() const
575       { return _M_owns; }
576
577       /* explicit */ operator bool () const
578       { return owns_lock(); }
579
580       mutex_type*
581       mutex() const
582       { return _M_device; }
583
584     private:
585       mutex_type*       _M_device;
586       bool              _M_owns; // XXX use atomic_bool
587     };
588
589   template<typename _Mutex>
590     inline void
591     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y)
592     { __x.swap(__y); }
593
594   template<typename _Mutex>
595     inline void
596     swap(unique_lock<_Mutex>&& __x, unique_lock<_Mutex>& __y)
597     { __x.swap(__y); }
598
599   template<typename _Mutex>
600     inline void
601     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>&& __y)
602     { __x.swap(__y); }
603
604   template<typename _L1, typename _L2, typename ..._L3>
605     int
606     try_lock(_L1& __l1, _L2& __l2, _L3&... __l3);
607
608   template<typename _L1, typename _L2, typename ..._L3>
609     void
610     lock(_L1&, _L2&, _L3&...);
611
612   /// once_flag
613   struct once_flag
614   {
615     typedef __gthread_once_t __native_type;
616
617     once_flag()
618     {
619       __gthread_once_t __tmp = __GTHREAD_ONCE_INIT;
620       _M_once = __tmp;
621     }
622     
623     once_flag(const once_flag&) = delete;
624     once_flag& operator=(const once_flag&) = delete;
625
626     template<typename _Callable, typename... _Args>
627       friend void
628       call_once(once_flag& __once, _Callable __f, _Args&&... __args);
629
630   private:
631     __native_type  _M_once;
632   };
633
634 #ifdef _GLIBCXX_HAVE_TLS
635   extern __thread void* __once_callable;
636   extern __thread void (*__once_call)();
637
638   template<typename _Callable>
639     void __once_call_impl()
640     {
641       (*(_Callable*)__once_callable)();
642     }
643 #else
644   extern function<void()> __once_functor;
645   extern unique_lock<mutex> __once_functor_lock;
646 #endif
647
648   extern "C" void __once_proxy();
649
650   template<typename _Callable, typename... _Args>
651     void
652     call_once(once_flag& __once, _Callable __f, _Args&&... __args)
653     {
654 #ifdef _GLIBCXX_HAVE_TLS
655       auto __bound_functor = bind(__f, __args...);
656       __once_callable = &__bound_functor;
657       __once_call = &__once_call_impl<decltype(__bound_functor)>;
658 #else
659       __once_functor_lock.lock();
660       __once_functor = bind(__f, __args...);
661 #endif
662      
663       int __e = __gthread_once(&(__once._M_once), &__once_proxy);
664
665 #ifndef _GLIBCXX_HAVE_TLS      
666       if (__once_functor_lock)
667         __once_functor_lock.unlock();
668 #endif
669
670       if (__e)
671         __throw_system_error(__e);
672     }
673 }
674
675 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
676
677 #endif // __GXX_EXPERIMENTAL_CXX0X__
678
679 #endif // _GLIBCXX_MUTEX