OSDN Git Service

2008-05-06 Benjamin Kosnik <bkoz@redhat.com>
[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 #endif
43
44 #include <exception>
45 #include <cstddef>
46 #include <bits/functexcept.h>
47 #include <bits/gthr.h> 
48
49 namespace std 
50 {
51   // XXX
52   class system_time;
53
54   /// mutex
55   class mutex
56   {
57   public:
58     typedef __gthread_mutex_t native_handle_type;
59
60     mutex()
61     {
62 #if defined __GTHREAD_MUTEX_INIT
63       native_handle_type __tmp = __GTHREAD_MUTEX_INIT;
64       _M_mutex = __tmp;
65 #else
66       int __e = __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); 
67
68       // EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
69       if ( __e)
70        __throw_system_error(__e);      
71 #endif
72     }
73
74     void 
75     lock()
76     {
77       int __e = __gthread_mutex_lock(&_M_mutex);
78
79       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
80      if ( __e)
81        __throw_system_error(__e);
82     }
83  
84     bool 
85     try_lock()
86     {
87       int __e = __gthread_mutex_trylock(&_M_mutex);
88
89       // EINVAL, EAGAIN, EBUSY
90      if ( __e)
91        __throw_system_error(__e);
92      else
93        return true;
94     }
95
96     void 
97     unlock()
98     {
99       int __e = __gthread_mutex_unlock(&_M_mutex);
100
101       // EINVAL, EAGAIN, EPERM
102      if ( __e)
103        __throw_system_error(__e);
104     }
105
106     native_handle_type 
107     native_handle()
108     { return _M_mutex; }
109
110   private:
111     native_handle_type _M_mutex;
112     mutex(const mutex&);
113     mutex& operator=(const mutex&);
114   };
115
116
117   /// recursive_mutex
118   class recursive_mutex
119   {
120   public:
121     typedef __gthread_recursive_mutex_t native_handle_type;
122
123     recursive_mutex()
124     { 
125 #if defined __GTHREAD_RECURSIVE_MUTEX_INIT
126       native_handle_type __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
127       _M_mutex = __tmp;
128 #else
129       int __e = __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
130
131       // EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
132       if ( __e)
133        __throw_system_error(__e);      
134 #endif
135     }
136
137
138     void 
139     lock()
140     { 
141       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
142
143       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
144      if ( __e)
145        __throw_system_error(__e);
146     }
147   
148     bool 
149     try_lock()
150     {
151       int __e = __gthread_recursive_mutex_trylock(&_M_mutex);
152
153       // EINVAL, EAGAIN, EBUSY
154      if ( __e)
155        __throw_system_error(__e);
156      else
157        return true;
158     }
159
160     void 
161     unlock()
162     { 
163       int __e = __gthread_recursive_mutex_unlock(&_M_mutex);
164
165       // EINVAL, EAGAIN, EBUSY
166      if ( __e)
167        __throw_system_error(__e);
168     }
169
170     native_handle_type 
171     native_handle() { return _M_mutex; }
172
173   private:
174     native_handle_type _M_mutex;
175
176     recursive_mutex(const recursive_mutex&);
177     recursive_mutex& operator=(const recursive_mutex&);
178   };
179
180
181   // class timed_mutex;
182   // class recursive_timed_mutex;
183
184   /// Do not acquire ownership of the mutex.
185   struct defer_lock_t { };
186
187   /// Try to acquire ownership of the mutex without blocking.
188   struct try_to_lock_t { };
189
190   /// Assume the calling thread has already obtained mutex ownership
191   /// and manage it.
192   struct adopt_lock_t { };
193
194   extern const defer_lock_t     defer_lock;
195   extern const try_to_lock_t    try_to_lock;
196   extern const adopt_lock_t     adopt_lock;
197
198   /// Thrown to indicate errors with lock operations.
199   class lock_error : public exception
200   {
201   public:
202     virtual const char* 
203     what() const throw();
204   };
205   
206   /// @brief  Scoped lock idiom.
207   // Acquire the mutex here with a constructor call, then release with
208   // the destructor call in accordance with RAII style.
209   template<typename _Mutex> 
210     class lock_guard
211     {
212     public:
213       typedef _Mutex mutex_type;
214
215       explicit lock_guard(mutex_type& __m) : _M_device(__m)
216       { _M_device.lock(); }
217
218       lock_guard(mutex_type& __m, adopt_lock_t __a) : _M_device(__m)
219       { _M_device.lock(); }
220
221       ~lock_guard()
222       { _M_device.unlock(); }
223
224     private:
225       mutex_type&  _M_device;
226       lock_guard(lock_guard const&);
227       lock_guard& operator=(lock_guard const&);
228     };
229
230   /// unique_lock
231   template<typename _Mutex> 
232     class unique_lock
233     {
234     public:
235       typedef _Mutex mutex_type;
236
237       unique_lock() : _M_device(NULL), _M_owns(false) { }
238
239       explicit unique_lock(mutex_type& __m) : _M_device(&__m)
240       { 
241         lock(); 
242         _M_owns = true;
243       }
244       
245       unique_lock(mutex_type& __m, defer_lock_t) 
246       : _M_device(&__m), _M_owns(false) { }
247
248       unique_lock(mutex_type& __m, try_to_lock_t) 
249       : _M_device(&__m), _M_owns(_M_device->try_lock()) { }
250
251       unique_lock(mutex_type& __m, adopt_lock_t) 
252       : _M_device(&__m), _M_owns(true)
253       {
254         // XXX calling thread owns mutex
255       }
256
257       unique_lock(mutex_type& __m, const system_time& abs_time);
258
259       template<typename _Duration>
260         unique_lock(mutex_type& __m, const _Duration& rel_time);
261
262       ~unique_lock()
263       {
264         if (_M_owns)
265           unlock();
266       }
267
268       unique_lock(unique_lock&&);
269
270       unique_lock& operator=(unique_lock&&);
271
272
273       void 
274       lock()
275       { 
276         if (_M_device && !_M_owns)
277           _M_device->lock(); 
278         else
279           throw lock_error();
280       }
281
282       bool 
283       try_lock()
284       { 
285         bool __ret = false;
286         if (_M_device && !_M_owns)
287           __ret = _M_device->try_lock(); 
288         else
289           throw lock_error();
290         return __ret;
291       }
292
293       void 
294       unlock()
295       { 
296         if (_M_device && _M_owns)
297           _M_device->unlock(); 
298         else
299           throw lock_error();
300       }
301
302
303       template<typename _Duration>
304         bool timed_lock(const _Duration& rel_time);
305
306       bool 
307       timed_lock(const system_time& abs_time);
308
309       void 
310       swap(unique_lock&& __u);
311
312       mutex_type* 
313       release() 
314       { 
315         mutex_type* __ret = _M_device; 
316         _M_device = NULL;
317         _M_owns = false;
318         return __ret;
319       }
320
321       bool 
322       owns_lock() const { return _M_owns; }
323
324       operator bool () const { return owns_lock(); }
325
326       mutex_type* 
327       mutex() const
328       { return _M_device; }
329
330     private:
331       unique_lock(unique_lock const&);
332       unique_lock& operator=(unique_lock const&);
333
334       mutex_type*       _M_device;
335       bool              _M_owns; // XXX use atomic_bool
336     };
337
338   template<typename _Mutex>
339     void 
340     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y);
341
342   template<typename _Mutex>
343     void 
344     swap(unique_lock<_Mutex>&& __x, unique_lock<_Mutex>& __y);
345
346   template<typename _Mutex>
347     void 
348     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>&& __y);
349
350   template<typename _L1, typename _L2, typename ..._L3> 
351     int 
352     try_lock(_L1&, _L2&, _L3&...);
353
354   template<typename _L1, typename _L2, typename ..._L3> 
355     void 
356     lock(_L1&, _L2&, _L3&...);
357
358   /// once_flag
359   struct once_flag 
360   {
361     typedef __gthread_once_t __native_type;
362
363     once_flag() : _M_once(__GTHREAD_ONCE_INIT) { }
364
365     __native_type&
366     _M_get() { return _M_once; }
367
368   private:
369     __native_type  _M_once;
370     once_flag(const once_flag&);
371     once_flag& operator=(const once_flag&);
372   };
373
374   template<typename _Callable, typename... _Args>
375     void 
376     call_once(once_flag& __once, _Callable __f, _Args&&... __args)
377     {
378       int __e = __gthread_once(&(__once._M_get()), __f(__args...)); 
379       if ( __e)
380         __throw_system_error(__e);
381     }
382 }
383
384
385 #endif