OSDN Git Service

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